﻿// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.IO;
using System.Linq;
using Xunit;

using static DocumentFormat.OpenXml.Tests.TestAssets;

#pragma warning disable CS8981
using a = DocumentFormat.OpenXml.Drawing;
using pic = DocumentFormat.OpenXml.Drawing.Pictures;
using w = DocumentFormat.OpenXml.Wordprocessing;
using wp = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using x = DocumentFormat.OpenXml.Spreadsheet;
#pragma warning restore CS8981

namespace DocumentFormat.OpenXml.Tests
{
    /// <summary>
    /// Summary description for OpenXmlPackageTest
    /// </summary>
    public class OpenXmlPackageTest
    {
        [Fact]
        public void AutoSaveTestDocxNoWrite()
        {
            byte[] GetBytes(Stream input)
            {
                input.Position = 0;

                using (var ms = new MemoryStream())
                {
                    input.CopyTo(ms);
                    input.Position = 0;

                    return ms.ToArray();
                }
            }

            using (var stream = GetStream(TestFiles.Complex0docx))
            {
                var dataBefore = GetBytes(stream);

                // open the file in readonly mode, nothing should be saved on disposing
                using (var document = WordprocessingDocument.Open(stream, false))
                {
                    document.MainDocumentPart.Document.Body.Append(new Paragraph());
                }

                Assert.Equal(dataBefore, GetBytes(stream));
            }
        }

        [Fact]
        public void AutoSaveTestDocx()
        {
            // Open and close the file with SDK to normalize the file
            // since the SDK will change contents when closing the package.
            Stream NormalizeDocument(Stream input)
            {
                using (var doc = WordprocessingDocument.Open(input, true))
                {
                }

                return input;
            }

            using (var stream = GetStream(TestFiles.Complex0docx, true))
            {
                NormalizeDocument(stream);

                // open the file in readWrite mode, and then changes should be saved
                using (var document = WordprocessingDocument.Open(stream, true))
                {
                    var firstText = document.MainDocumentPart.Document.Descendants<Text>().First();

                    // change text of the first run
                    firstText.Text = "Changed";

                    var stylePart = document.MainDocumentPart.GetPartsOfType<StyleDefinitionsPart>().First();
                    var heading1Style = stylePart.Styles.Descendants<Style>().Where(style => style.StyleId == "Heading1").Single();

                    // change color to be black
                    heading1Style.Descendants<Color>().First().Val = "000000";
                }

                // check the changes. other parts should be the same
                using (var document = WordprocessingDocument.Open(stream, false))
                {
                    var firstText = document.MainDocumentPart.Document.Descendants<Text>().First();
                    Assert.Equal("Changed", firstText.Text);
                    var stylePart = document.MainDocumentPart.GetPartsOfType<StyleDefinitionsPart>().First();
                    var heading1Style = stylePart.Styles.Descendants<Style>().Where(s => s.StyleId == "Heading1").Single();
                    Assert.Equal("000000", heading1Style.Descendants<Color>().First().Val.Value);
                }

                using (var originalStream = GetStream(TestFiles.Complex0docx))
                using (var originalDoc = WordprocessingDocument.Open(originalStream, false))
                using (var changedDoc = WordprocessingDocument.Open(stream, false))
                {
                    var changedDocIterator = changedDoc.GetAllParts();
                    var changedDocEnumerator = changedDocIterator.GetEnumerator();

                    foreach (var originalPart in originalDoc.GetAllParts())
                    {
                        Assert.True(changedDocEnumerator.MoveNext());
                        if (!(originalPart is MainDocumentPart) && !(originalPart is StyleDefinitionsPart))
                        {
                            Assert.Equal(originalPart.GetType(), changedDocEnumerator.Current.GetType());
                            Assert.Equal(originalPart.GetStream().Length, changedDocEnumerator.Current.GetStream().Length);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// AutoSaveTestCreate.
        /// </summary>
        [Fact]
        public void AutoSaveTestCreate()
        {
            // Create with a memory stream
            using (var document = WordprocessingDocument.Create(new MemoryStream(), DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
            {
                document.AddMainDocumentPart();
                document.MainDocumentPart.Document = new Document();
            }

            // Create with file stream
            using (var stream = new MemoryStream())
            {
                using (var document = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document))
                {
                    document.AddMainDocumentPart();
                    document.MainDocumentPart.Document =
                        new Document(
                            new Body(
                                new Paragraph(
                                    new Run(
                                        new Text("Hello World")))));

                    // add an image
                    var imagePart1 = document.MainDocumentPart.AddNewPart<ImagePart>("image/x-wmf", "rId6");
                    using (var writer = new BinaryWriter(imagePart1.GetStream()))
                    {
                        writer.Write(Convert.FromBase64String("183GmgAAAABGAI0F6gVeAgAAAABuVQEACQAAA2IvAAADADAHAAAAAAUAAAAMAqQFjQUFAAAACwJGAAAABAAAAAUBAQAEAAAABAENAAQAAAAGAQEABAAAAAIBAgAFAAAAAQL/////BAAAAC4BGAAIAAAA+gIFAAAAAAAAAAAABAAAAC0BAAAHAAAA/AIAAOby/wAAAAQAAAAtAQEAGAIAACQDCgEgAUcDIQFIAyUBSwMnAU4DKgFRAy4BUwMzAVcDLwFcAysBYQMqAWQDKQFnAygBagMnAW0DJgFwAyYBcgMlAXUDJQF4AyUBewMlAX4DJQGBAyYBhQMmAYcDJgGKAycBjQMoAZADKQGSAyoBlQMrAZgDLQGbAzABoAMzAaUDNQGnAzgBqgM6AawDPQGvA0EBsQNHAbQDSQG1A0wBtwNPAbgDUgG5A1QBuQNXAboDWgG6A10BugNgAboDYwG6A2UBugNpAbsDawG6A24BuQNxAbkDdAG5A3YBuAN5AbcDfAG2A38BtQOEAbEDiQGvA40BqgOSAaYDoAGrA6UBtQOiAbgDnwG6A5wBvQOaAcADlwHDA5UBxgOSAckDkAHNA44BzwOMAdMDigHXA4kB2gOHAd4DhQHiA4QB5gODAeoDgQHtA4AB8QN+AfUDfQH5A3sB/QN6AQEEeQEFBHkBCgR4AQ0EeAERBHcBFQR2ARkEdQEdBHUBIQR0ASUEdAEqBHMBLQRzATEEcgE0BHIBOARyATwEcgE/BHIBQwRyAUcEcgFJBHIBTQRyAVAEcgFTBHIBVgRyAVkEcgFcBHIBXwRyAWMEcgFoBHIBbARyAW8EcgFxBHMBdARzAXUEcwF2BFEBdgRQAW4EUAFmBE8BXwRPAVgETgFRBE4BSgRNAUQETQE+BEwBNwRMATIESwEsBEoBJwRJASEESQEcBEgBFgRIARIERwENBEYBCARFAQQERAEABEMB+wNCAfcDQQH0A0AB8AM+AewDPQHpAz0B5QM8AeIDOwHfAzoB3AM5AdoDOAHYAzYB1QM1AdIDNAHPAzMBzgMwAckDLgHFAywBwgMqAb8DKAG8AyYBugMiAbUDHwGyAx0BsAMbAa8DGAGsAxYBqQMTAacDEQGlAw4BowMLAaEDCAGgAwUBngMCAZ0D/wCbA/sAmgP4AJkD9QCYA/EAlwPuAJYD6wCVA+cAlAPkAJMD4ACSA9wAkgPZAJED1QCRA9EAkQPOAJEDygCQA8YAkAPDAJADvwCQA7wAkAO4AJADtACQA7IAkQOuAJEDqgCRA6cAkQOjAJEDoACRA50AkQOZAJIDlgCSA5MAkgOQAJMDjQCTA4sAlAOIAJQDhQCVA4MAlQOBAJYDfACWA3gAlwN1AJgDcgCZA24AmQNtAJoDdABoA3kAaAN/AGgDhQBoA4sAaAOQAGgDlQBoA5sAaAOgAGgDpQBoA6kAaAOuAGgDswBoA7cAZwO8AGYDwABmA8UAZgPJAGUDzQBlA9AAZAPUAGQD2ABjA9sAYgPfAGED4wBhA+UAYAPpAF8D7ABeA+8AXQPxAFwD9ABcA/cAWwP6AFsD/gBZAwMBVwMHAVUDCwFTAw4BUgMRAVADFAFPAxcBTQMbAUoDHgFJAx8BRwMgAUcDIAFHA/IBAAAkA/cAZgFqBGcBwwSEAcMEkQGbBM0BigT0AaUEIQKLBB4CXQQ/AjsEbAJABIwCDgRxAukDgwKrA6kCpAOpAqADqQKbA6kCmAOpApQDqQKQA6kCiwOpAocDqQKEA6kCfwOpAnwDqQJ3A6kCcwOpAm8DqQJrA6kCaAOpAmQDggJYA3ECGwOMAvUCcgLHAkMCygIiAqkCJwJ7AvUBXALQAXcCkgFlAosBPgJlATwCUQFmAmcBlwJoAZcCawGXAm0BlwJwAZcCcwGXAngBmAJ7AZgCgAGYAoMBmAKFAZkCiAGZAosBmgKNAZoCkAGbApMBmwKWAZwCmAGcApsBnQKfAZ4CogGfAqUBoAKoAaECqwGhAq4BowKxAaQCtQGkArgBpQK8AacCvwGoAsIBqQLGAasCygGsAswBrgLQAa8C1AGxAtcBswLaAbUC3gG3AuEBuQLlAbsC6AG9AusBvwLuAcIC8gHEAvUBxwL4AckC+wHMAv4BzwIBAtICBQLVAggC2AILAtwCEALgAhUC5QIXAucCGQLqAhsC7AIeAu8CIgL0AiYC+QInAvwCKgL/AisCAgMtAgUDLwIHAzACCgMyAgwDMwIPAzUCEgM2AhUDNwIYAzkCGwM6Ah0DOwIgAzwCIwM+AiYDPwIpA0ACKwNBAi4DQgIxA0MCMwNEAjYDRQI5A0YCPANGAj8DRwJBA0gCRANJAkcDSQJJA0oCTANKAk8DSwJSA0sCVANMAlcDTAJaA00CXANOAmEDTwJmA08CawNQAnADUAJ0A1ECeQNRAn0DUgKCA1IChANSAoYDUQKIA1ECiwNRAo4DUAKSA1AClgNPApoDTgKeA00CowNMAqUDTAKnA0sCqgNLAq0DSwKvA0oCsgNJArUDSQK4A0gCuwNHAr4DRgLBA0YCxANEAscDQwLKA0ICzQNBAs8DQALSAz8C1gM+AtgDPQLcAzsC3wM6AuIDOALlAzcC6AM1AusDNALuAzIC8gMxAvUDLgL4Ay0C+wMrAv4DKQIBBCYCBAQkAgcEIwIKBCECDQQeAhAEGwITBBkCFgQXAhkEFAIcBBECHwQPAiEEDAIkBAsCJQQJAicEBgIqBAICLgT+ATEE/AEzBPgBNgT0ATkE8AE8BOwBPwToAUIE4wFGBOABRwTdAUgE2gFKBNcBTATUAU0E0QFPBM4BUATLAVIExwFTBMQBVQTAAVYEvQFYBLkBWQS2AVsEsgFcBK8BXQSrAV4EpgFfBKIBYASeAWIEmQFjBJUBZASRAWUEjQFmBIgBZwSDAWcEfgFnBHoBaAR1AWkEcAFpBGsBagRmAWoEZgFqBPIBAAAkA/cAbAGXAmoBPAJNAT0CQgFmAgUBdgLeAFsCsQB1ArMAowKTAMYCZQC/AkUA8QJhABYDTwBWAygAXQMoAGADKABkAygAaAMoAGwDKABwAygAcwMoAHgDKAB8AygAgAMoAIQDKACIAygAjAMoAJADKACVAygAmQMoAJ0DUACpA2EA5QNFAAwEYAA4BI4ANgSwAFcEqgCEBNwApAQBAYkEPwGbBEYBwgRtAcMEgQGaBGoBagRpAWoEZQFqBGMBaQRgAWkEXQFpBFkBaQRUAWgEUAFnBEsBZgRGAWYEQwFlBEABZAQ9AWQEOwFjBDgBYgQ1AWIEMgFhBC8BYQQsAV8EKQFeBCUBXQQiAV0EHwFbBBsBWgQYAVkEFQFYBBEBVgQOAVUECgFTBAcBUgQDAVAEAAFPBPwATQT5AEwE9gBJBPIASATvAEYE7ABEBOgAQQTlAD8E4gA9BN8AOwTbADgE2AA1BNUAMwTSADAEzwAtBMwAKgTJACcExgAkBMQAIQTBAB8EvgAdBLwAGgS3ABUEswAQBLEADQSvAAsErAAIBKoABQSoAAIEpwAABKUA/QOjAPsDoQD4A58A9QOeAPIDnQDvA5sA7AOaAOoDmADnA5cA5AOWAOIDlQDfA5QA3AOTANkDkQDXA5AA1AOPANEDjwDOA40AzAOMAMkDiwDGA4sAwwOKAMADigC9A4kAugOIALgDhwC1A4cAsgOGAK8DhQCtA4QApwOEAKMDgwCgA4MAnQOCAJsDggCYA4EAkwOBAI8DgQCKA4EAhgOBAIEDgQB9A4EAewOBAHkDgQB2A4EAdAOBAHADgQBtA4EAaAOCAGUDggBgA4MAWwOEAFYDhQBRA4YATgOHAEsDhwBJA4gARgOJAEMDigBAA4oAPQOLADsDjAA4A40ANQOOADIDjwAvA5AAKwORACkDkwAlA5QAIgOVAB8DlgAcA5gAGQOZABYDmwATA5wAEAOeAA0DoAAKA6EABwOjAAMDpQAAA6cA/QKpAPoCqwD3Aq0A9QKwAPICsgDvArQA7AK3AOkCugDmArwA4wK/AOECwgDeAsYA3ALGANsCyADZAssA1QLQANEC0gDOAtUAzALYAMkC3ADGAuAAwwLkAMAC5gC/AukAvQLsALwC7gC6AvEAuQLzALcC9gC1AvkAtAL8ALIC/wCwAgIBrwIFAa4CCAGsAgwBqwIPAakCEwGoAhYBpgIaAaUCHgGkAiIBowImAaECKgGgAi4BnwIyAZ4CNgGcAjsBmwI/AZoCRAGaAkgBmQJNAZkCUQGYAlcBmAJbAZcCYQGXAmYBlwJsAZcCbAGXAgcAAAD8AgAA4PL8AAAABAAAAC0BAgAEAAAA8AEBAAgCAAAkAwIBXgEFBGkBFQR0ASYEgAE2BIwBRwSXAVYEowFmBLABdQS9AYUEyQGTBNYBogTjAa8E8QG+BP0BywQLAtkEGQLmBCcC8wQ0Av8EQgIMBVACFwVfAiIFbAItBXsCOAWJAkMFmAJNBaYCVwW0AmAFwgJpBdECcgXgAnsF7gKDBf0CiwUMA5MFGgOZBSgDoAU3A6YFRQOsBVQDsQVjA7cFcQO7BYADwAWNA8MFnAPHBakDygW4A84FxgPPBdMD0gXhA9MF7wPVBfwD1gUJBNYFFgTWBSME1gUwBNQFPQTTBUkE0QVWBNAFYgTNBW4EygV6BMYFhgTDBZEEvgWcBLkFpwSzBbMErgW9BKcFxwShBdAEmQXaBJIF4gSKBesEggXzBHkF+wRwBQMFZgUKBV0FEQVTBRgFSQUeBT4FJAUzBSoFKAUvBR0FNAURBTgFBQU8BfgEQQXsBEQF3wRIBdIESwXFBE0FuARPBaoEUQWcBFMFjgRUBYAEVQVxBFYFYgRWBVMEVgVFBFUFNQRVBSUEUwUVBFIFBgRPBfYDTQXmA0sF1gNIBcYDRAW1A0EFpQM9BZQDOQWDAzUFcgMwBWEDKwVRAyUFQAMfBS8DGQUeAxIFDAMMBfsCBAXqAv0E2QL1BMgC7QS3AuQEpQLcBJQC0gSDAskEcQK/BGACtQRPAqoEPgKgBC0ClAQcAogECwJ8BPsBcQTrAWUE2wFZBMwBTAS8AUAErgEzBJ4BJgSQARkEggENBHQB/wNmAfIDWgHlA00B1wNBAckDNAG7AygBrQMdAZ8DEQGRAwYBgwP7AHUD8QBnA+cAWAPdAEoD1AA7A8sALQPDAB4DugAQA7IAAgOrAPQCpADlApwA1wKVAMgCjwC6AokAqwKDAJ0CfgCPAnkAgAJ1AHICcABkAmwAVQJoAEgCZgA5AmMALAJgAB4CXgARAl0AAwJcAPYBWwDoAVoA2wFaAM4BWgDBAVsAtQFcAKgBXQCbAV8AjwFiAIQBZAB4AWcAbAFqAGEBbwBVAXMASwF4AD8BfAA1AYIAKwGIACEBjwAYAZYADwGdAAYBpQD/AK4A9gC2AO8AvwDoAMkA4QDTANoA3QDVAOgAzwDzAMoA/wDEAAoBwAAWAbwAIgG4AC8BswA8AbEASQGuAFcBqwBlAagAcwGnAIEBpgCQAaUAnwGkAK4BpAC9AaMAzQGkAN0BpADtAaUA/QGnAA0CqAAeAqkALgKsAD4CrwBQArIAYQK1AHICuQCDArwAlALBAKYCxgC3AssAyQLQANoC1gDsAtwA/gLiAA8D6QAhA/AAMwP3AEQD/wBWAwcBaAMPAXoDGAGLAyEBnAMqAa4DNAHAAz0B0QNIAeIDUwH0A14BBQReAQUEBwAAAPwCAAD///8AAAAEAAAALQEBAAQAAADwAQIAgAAAACQDPgD3AowANgO7ANYBwQDcAbwA4QG4AOgBtADuAbEA8wGtAPoBqgAAAqcABgKkAAwCoQATAp4AGQKcAB8CmgAlApcALAKVADICkwA4ApIAPgKQAEQCjgBLAo0AUQKLAFYCigBdAogAYwKHAGkChwBvAoYAdAKFAHoChACAAoQAhQKDAIsCggCQAoIAlgKCAJsCggCfAoEApAKBAKkCgQCuAoEAswKBALcCgQC8AoIAwAKCAMQCggDIAoIAzAKDAM8CgwDTAoMA1wKEANoChADdAoQA4AKFAOMChQDmAoYA6wKGAO8CiADyAokA9QKKAPYCiwD3AowA9wKMAIQAAAAkA0AAXgU4BS8FdAUNBHgFEgRzBRgEbwUeBGsFJQRoBSsEZAUyBGEFOAReBT8EWwVGBFgFTQRVBVMEUgVbBFAFYQRNBWgESwVwBEkFdwRHBX0ERQWEBEMFiwRBBZIEQAWZBD4FoAQ9BacEPAWuBDsFtQQ5BbwEOAXCBDcFyQQ2BdAENQXWBDUF3QQ0BeQENAXpBDMF8AQzBfYEMgX8BDIFAgUyBQcFMgUNBTIFEwUyBRgFMgUdBTIFIgUyBScFMgUrBTIFMAUyBTQFMgU5BTMFPAUzBUAFMwVDBTMFRwUzBUoFMwVNBTQFUAU0BVMFNQVXBTUFWgU2BVwFNwVeBTgFXgU4BQcAAAD8AgAAlqu6AAAABAAAAC0BAgAEAAAA8AEBANoBAAAkA+sAxAGMBM0BigT0AaUEIQKLBB4CXQQ/AjsEbAJABIwCDgRxAukDgwKrA6kCpAOpAqADqQKbA6kCmAOpApQDqQKQA6kCiwOpAocDqQKEA6kCfwOpAnwDqQJ3A6kCcwOpAm8DqQJrA6kCaAOpAmQDggJYA3ECGwOMAvUCcgLHAkMCygIiAqkCKAJ7AvUBXQLQAXcCkgFlAosBPgJlAT0CUQFmAmcBlwJoAZcCawGXAm0BlwJwAZcCcwGXAngBmAJ7AZgCgAGYAoMBmAKFAZkCiAGZAosBmgKNAZoCkAGbApMBmwKWAZwCmAGcApsBnQKfAZ4CogGfAqUBoAKoAaECqwGhAq4BowKxAaQCtQGkArgBpQK8AacCvwGoAsIBqQLGAasCygGsAswBrgLQAa8C1AGxAtcBswLaAbUC3gG3AuEBuQLlAbsC6AG9AusBvwLuAcIC8gHEAvUBxwL4AckC+wHMAv4BzwIBAtICBQLVAggC2AILAtwCEALgAhUC5QIXAucCGQLqAhsC7AIeAu8CIgL0AiYC+QInAvwCKgL/AisCAgMtAgUDLwIHAzACCgMyAgwDMwIPAzUCEgM2AhUDNwIYAzkCGwM6Ah0DOwIgAzwCIwM+AiYDPwIpA0ACKwNBAi4DQgIxA0MCMwNEAjYDRQI5A0YCPANGAj8DRwJBA0gCRANJAkcDSQJJA0oCTANKAk8DSwJSA0sCVANMAlcDTAJaA00CXANOAmEDTwJmA08CawNQAnADUAJ0A1ECeQNRAn0DUgKCA1IChANSAoYDUQKIA1ECiwNRAo4DUAKSA1AClgNPApoDTgKeA00CowNMAqUDTAKnA0sCqgNLAq0DSwKvA0oCsgNJArUDSQK4A0gCuwNHAr4DRgLBA0YCxANEAscDQwLKA0ICzQNBAs8DQALSAz8C1gM+AtgDPQLcAzsC3wM6AuIDOALlAzcC6AM1AusDNALuAzIC8gMxAvUDLgL4Ay0C+wMrAv4DKQIBBCYCBAQkAgcEIwIKBCECDQQeAhAEGwITBBkCFgQXAhkEFAIcBBECHwQPAiEEDAIkBAsCJAQKAiYECAIoBAUCKwQBAi4E/AEyBPoBNAT3ATYE9AE5BPIBPATuAT4E6gFABOYBQwTiAUYE3gFIBNkBSgTUAU0E0AFQBM0BUQTKAVIExwFTBMUBVATCAVUEvwFWBLwBWAS6AVkEtgFaBLQBWwSwAVwErQFdBKoBXgSnAV8EowFgBKEBYQTEAYwExAGMBG4AAAAkAzUAzwDTAtIAzgLXAMsC2gDIAtwAxgLfAMMC4wDCAuUAvwLpALwC7QC6AvEAuAL2ALUC+gCzAv8AsAIEAa4CCAGsAg0BqgIQAagCEwGnAhYBpgIZAaUCHAGkAh8BowIhAaICJAGhAicBoAIqAaACLgGfAjEBngI0AZ0CNwGcAjsBmwI+AZsCQQGaAkUBmgJIAZkCTAGZAlABmAJTAZgCVwGXAlsBlwJfAZcCYwGXAmcBlwJsAZcCagE9Ak0BPQJCAWYCBQF2At4AWwK3AHECzwDTAs8A0wJkAQAAJAOwAAEBWAMFAVYDCQFVAwwBUwMPAVIDEgFQAxUBTwMXAU0DGQFMAxwBSQMfAUgDIAFHAyEBRwMiAUgDJgFLAykBTAMsAU8DMAFSAzQBVgMwAVsDLAFgAysBYwMqAWYDKQFoAygBbAMnAW8DJwFyAyYBdAMmAXcDJgF6AyYBfQMmAYADJwGEAycBhgMnAYkDKAGMAykBjwMqAZIDKwGVAywBmAMuAZsDMQGfAzUBpAM3AaYDOQGoAzwBqwM+Aa0DQwGwA0gBswNLAbQDTgG2A1EBtwNTAbgDVgG4A1kBuQNbAbkDXgG5A2EBuQNkAbkDZwG5A2oBugNtAbkDbwG5A3IBuAN1AbgDeAG3A3oBtgN9AbUDgAG0A4UBsAOKAa4DjgGpA5MBpQOXAagDmwGrA54BrgOhAbADpQG0A6YBtQOjAbgDoAG6A50BvQObAcADmAHDA5YBxQOUAckDkgHNA48BzwOOAdMDjAHXA4oB2gOIAd4DhwHiA4UB5QOEAeoDgwHtA4EB8QOAAfUDfgH5A30B/QN8AQEEewEFBHoBCQR5AQ0EeQERBHgBFQR4ARkEdwEdBHYBIQR2ASUEdgEqBHMBJQRwASEEbgEdBGsBGQRpARUEZwESBGQBDgRiAQsEXwEHBF0BBARbAQAEWQH9A1cB+QNVAfYDUwHzA1EB8ANPAewDTQHpA0sB5gNJAeMDRwHgA0YB3ANEAdkDQgHXA0AB0wM+AdADPQHOAzsBywM5AcgDOAHFAzYBwgM1Ab8DMwG8AzEBuQMvAbYDLgGzAywBsAMqAa0DKQGqAygBpwMmAaQDJAGhAyMBngMhAZsDIAGYAx4BlQMdAZIDGwGPAxkBjAMYAYgDFgGFAxUBggMTAX4DEQF7AxABeAMOAXUDDAFxAwsBbgMJAWoDCAFmAwYBYwMEAV8DAgFcAwEBWAMBAVgDGgIAACQDCwGmAbUDpQG0A6EBsQOeAa4DmwGsA5cBqAOTAaUDlQGjA5cBoAOYAZ0DmQGaA5oBlwOcAZQDnQGRA54BjwOfAYwDnwGJA6ABhgOgAYMDoAGAA6ABfQOgAXsDoAF4A58BdAOfAXIDngFvA50BbAOcAWkDmwFmA5kBYwOYAWEDlwFeA5UBWwOTAVkDkQFXA40BUgOJAU4DhgFMA4QBSgOBAUkDfgFHA3sBRgN5AUUDdgFEA3MBQwNwAUIDbgFBA2sBQQNoAUEDZQFAA2IBQANfAUEDXQFBA1oBQQNXAUIDVAFCA1EBQwNOAUQDSwFFA0gBRgNGAUgDQQFKAzwBTQM4AVEDNAFWAycBUgMhAUcDIwFEAyYBQQMpAT8DKwE8Ay4BOAMwATUDMwEyAzUBLwM3ASsDOQEoAzsBJAM9ASADPgEdAz8BGQNBARUDQwESA0QBDQNFAQoDRgEFA0cBAQNIAf0CSQH5AkoB9gJMAfICTAHtAk0B6gJOAeUCTwHhAk8B3QJQAdkCUAHWAlEB0gJRAc4CUQHKAlEBxgJSAcMCUgG/AlMBuwJTAbgCUwG1AlMBsQJTAa4CUwGrAlMBqAJTAaQCUwGiAlMBnwJTAZ0CUwGYAlMBkwJTAZACUwGNAlMBigJTAYgCUwGHAnYBhwJ2AY4CdgGVAnYBnAJ2AaQCdgGqAncBsQJ3AbcCeAG+AngBwwJ5AckCeQHPAnoB1QJ6AdoCewHfAnwB5AJ9AeoCfgHuAn8B8wKAAfcCgQH7AoIB/wKDAQMDhAEHA4UBCwOGAQ4DhwESA4gBFQOJARgDigEbA4sBHgONASEDjgEkA5ABKQOSAS4DlAEyA5cBNgOYATkDmwE8A50BPwOfAUIDogFGA6YBSQOpAUwDqwFOA60BUAOvAVIDsgFUA7UBVgO3AVgDugFaA70BWwPAAV0DwwFeA8YBXwPKAWEDzQFiA9ABYwPUAWQD1wFlA9sBZgPeAWcD4QFoA+UBaAPoAWkD7AFpA/ABaQPzAWoD9wFqA/sBagP+AWoDAgJqAwYCawMJAmsDDQJrAxACawMUAmsDFwJrAxsCagMeAmoDIgJqAyQCaQMoAmkDKwJpAy4CaQMxAmgDNAJoAzcCaAM6AmgDPAJnAz8CZgNBAmYDRAJmA0gCZQNMAmUDUAJkA1MCYwNXAmIDWQJiA1EClANLApMDRQKTAz8CkgM5ApIDNAKSAy4CkgMpApIDJAKSAx8CkgMaApIDFQKTAxECkwMMApMDCAKUAwQClAMAApUD/AGVA/cBlgPzAZYD8AGXA+sBmAPoAZkD5QGZA+IBmgPeAZsD2wGbA9gBnAPVAZ0D0wGeA9ABnwPNAaADywGhA8YBowPBAaUDvQGmA7oBqAO2AakDswGrA7ABrQOuAa8DqwGxA6gBswOmAbQDpgG1A6YBtQMHAAAA/AIAAMzMvwAAAAQAAAAtAQEABAAAAPABAgDoAQAAJAPyAB0E7AQfBEsFOARJBUoEIAWLBA4FwgQkBd0EEwXjBN4ECwW2BD4FtARVBZEEPQVXBE8FHwR3BQMEeQXcA00FxgM7BYYDUQVMA0MFNQMLBS0D5gQKA+ME0QLEBL4CjwTVAkwEwgJFBJgCHASXAgcEwwIfBPcCIAT3AiME9wIlBPcCKQT3AiwE9wIwBPgCNQT4AjkE+AI8BPgCPwT5AkEE+QJEBPoCRwT6AkoE+wJNBPwCUAT9AlME/QJWBP4CWgT/Al0EAANgBAADZAQBA2cEAgNrBAMDbgQEA3IEBgN1BAcDeQQJA3wECgOABAsDhAQMA4cEDgOLBBADjwQRA5IEEwOXBBYDmgQXA54EGQOhBBsDpQQeA6gEHwOsBCIDrwQlA7MEKAO2BCoDugQtA70EMAPABDMDwwQ2A8cEOQPKBD0DzgRAA9AEQwPTBEUD1QRIA9gESgPbBE0D3QRQA98EUwPiBFUD5ARYA+YEWwPoBF4D6gRhA+wEZAPuBGYD8ARpA/IEbAP0BG8D9gRyA/cEdQP5BHgD+wR7A/wEfgP9BIED/wSEAwAFhwMCBYoDAwWNAwUFkAMFBZMDBwWWAwgFmQMJBZwDCgWfAwsFogMMBaUDDQWoAw0FqwMOBa4DDwWwAxAFtAMRBbcDEQW5AxEFvAMSBb8DEwXCAxMFxQMUBcgDFQXLAxUFzQMVBdADFgXSAxYF1QMWBdgDFwXaAxcF3QMYBeADGAXkAxkF6gMZBe4DGQXzAxkF9QMZBfcDGQX5AxkF/QMZBQAEGAUEBBgFCAQXBQ0EFgURBBUFFgQUBRkEFAUcBBMFHwQTBSEEEgUkBBIFJwQRBSoEEQUtBA8FMAQPBTQEDgU3BA4FOgQMBT0ECwVABAoFQwQJBUcEBwVJBAcFTQQFBVAEBAVUBAIFVwQBBVsE/wRdBP4EYQT8BGUE+wRoBPkEawT3BG8E9QRyBPMEdQTxBHkE7wR8BO0EfwTqBIME6ASGBOYEiQTjBIwE4QSQBN4EkgTcBJYE2QSZBNYEmwTTBJ4E0ASiBM8EogTNBKQEywSmBMoEpwTHBKkExQSsBMEErgS+BLEEugS0BLcEuASyBLoErQS+BKgEwQSjBMUEoATGBJ0EyASaBMoEmATMBJQEzQSRBM4EjgTQBIoE0gSGBNQEgwTVBH8E1wR7BNgEdwTZBHME2wRwBNwEbATeBGcE3wRjBOEEXgThBFoE4wRVBOQEUQTlBEwE5gRHBOcEQgTnBD0E6AQ3BOkEMwTqBC0E6gQoBOsEIgTrBB0E7AQdBOwEBgIAACQDAQEjBPcCIgSXAgIElwL2A8ICtQPUAooDtgJbA9MCXQMEAzoDKgMJAyID6QJYAwUDgAPyAsQDyQLLA8kCzgPIAtMDyALXA8gC2wPIAuADyALkA8gC6APIAu0DyALxA8gC9gPIAvoDyAL+A8gCAgTIAgcEyAILBMgCEATzAhwEBQNdBOwCjwT6AqoENgO1BFoD2ARfAxIFfAMkBbEDDQX1AyAFEARNBSQESwU6BB8FIgTsBCEE7AQdBOwEGQTsBBcE7AQTBOsEDwTrBAsE6gQGBOkEAwTpBAAE6AT9A+gE+wPoBPgD5wT1A+YE8QPmBO8D5QTrA+QE6APkBOUD4wTiA+IE3gPhBNsD4ATXA98E1APeBNAD3QTNA9wEyQPaBMYD2QTCA9cEvgPWBLoD1QS3A9MEswPRBK8DzwSrA80EqAPMBKQDygSgA8gEnQPFBJkDwwSVA8EEkgO+BI4DvASLA7kEhwO3BIQDtASAA7EEfgOuBHoDqwR3A6gEdAOkBHEDogRuA58EbAOcBGkDmQRmA5cEYwOUBGEDkQRfA48EXQOMBFoDiQRYA4YEVgOEBFQDgQRSA34EUAN7BE4DeARNA3UESgNyBEgDbwRGA2wERQNpBEQDZgRCA2MEQQNgBD8DXQQ+A1oEPANXBDsDVAQ6A1EEOQNOBDgDSwQ3A0gENgNGBDUDQgQ0Az8EMwM8BDIDOQQxAzYEMQMzBDADMAQvAy0ELgMqBC4DKAQtAyUELAMiBCwDHwQrAxwEKwMZBCsDFwQqAxQEKQMRBCkDDgQpAwsEKAMGBCgDAQQnA/wDJwP3AycD8wMnA+8DJwPsAycD6gMnA+cDJwPkAycD4QMnA90DKAPZAykD1QMpA88DKgPLAyoDyAMrA8UDKwPCAywDwAMsA7wDLQO5Ay4DtwMvA7QDLwOwAzADrgMxA6sDMgOoAzMDpAM0A6EDNQOdAzYDmwM3A5cDOAOUAzoDkAM7A40DPAOJAz4DhgM/A4MDQQOAA0IDfANEA3kDRgN2A0gDcwNKA28DTANsA04DaANQA2YDUgNiA1QDXwNXA1wDWQNZA1wDVQNeA1MDYQNQA2QDTQNnA0oDagNHA20DRANwA0IDcQNBA3MDPwN0Az0DdgM7A3gDOAN7AzYDfgMzA4EDMQOFAy0DiQMqA40DJwOSAyQDlAMiA5cDIAOaAx8DnQMeA58DHAOiAxoDpQMYA6gDFgOrAxUDrgMTA7IDEQO1AxADuQMOA7wDDAPAAwoDxAMJA8cDCAPMAwYD0AMFA9QDBAPYAwID3AMBA+EDAAPlA/8C6gP9Au8D/ALzA/sC+QP7Av0D+QIDBPkCBwT4Ag0E+AISBPcCFwT3Ah0E9wIjBPcCIwT3AgcAAAD8AgAAtdTrAAAABAAAAC0BAgAEAAAA8AEBAAgCAAAkAwIBDwMJBBcDCQQeAwgEJgMIBC4DBwQ1AwYEPQMFBEUDAwRMAwIEUwMBBFoD/wNiA/0DaQP7A3AD+AN3A/YDfgPzA4UD8QOLA+0DkwPqA5kD5wOgA+MDpgPgA6wD3AOyA9gDuQPUA78DzwPFA8sDygPHA9ADwwPWA70D2wO5A+EDtAPmA68D6wOpA/ADpAP1A54D+QOZA/4DkwMCBI0DBgSHAwsEggMPBHsDEwR1AxcEbwMaBGgDHgRhAyEEWwMkBFQDJwROAyoERwMsBD8DLwQ4AzEEMQMzBCkDNQQiAzcEGwM5BBQDOgQMAzsEBQM8BP0CPgT2Aj4E7gI/BOYCPwTfAj8E1wI/BM8CPwTHAj4EvwI+BLgCPASwAjsEqAI6BKECOQSaAjcEkgI1BIoCMwSDAjEEfAIvBHUCLARuAioEZwInBGACJARZAiEEUgIeBEwCGgRGAhcEPgITBDgCDwQyAgsELAIGBCYCAgQgAv4DGgL5AxUC9QMPAvADCgLrAwQC5gMAAuED+gHbA/UB1gPwAdAD7AHKA+cBxQPiAb8D3gG5A9oBsgPWAawD0gGmA84BoAPLAZkDxwGTA8QBiwPBAYUDvgF+A7sBdwO5AXADtgFpA7QBYgOxAVoDrwFTA64BTAOtAUUDqwE9A6kBNQOoAS4DqAEmA6cBHgOmARcDpgEPA6YBBwOmAf8CpgH3AqcB7wKoAegCqAHgAqkB2AKrAdECrQHKAq4BwgKvAbsCsQG0ArQBrQK2AaYCuQGfArsBmAK+AZECwQGKAsQBhALHAX0CywF2As4BcALSAWoC1gFkAtoBXgLeAVgC4gFSAucBTQLsAUcC8AFBAvUBPAL6ATcCAAIyAgQCLQIKAigCDwIjAhUCHwIaAhoCIAIWAiYCEgIsAg4CMgIKAjgCBgI+AgMCRgL/AUwC/AFSAvkBWQL2AWAC8wFnAvEBbgLuAXUC7AF8AukBgwLoAYoC5gGSAuUBmgLjAaEC4gGoAuEBsALgAbgC3wG/At8BxwLfAc8C3wHXAt8B3wLfAeYC3wHuAuAB9gLhAf0C4gEFA+MBDAPlARQD5gEbA+gBIgPpASkD7AExA+4BOAPxAT8D8wFHA/YBTgP5AVQD/AFbA/8BYQMDAmgDBgJvAwoCdQMOAnsDEgKCAxYChwMaAo0DHwKTAyMCmQMoAp4DLQKkAzICqQM3Aq8DPAK0A0ECuQNHAr0DTQLDA1ICxwNYAssDXgLPA2QC1ANqAtgDcALcA3YC4AN9AuMDhALnA4oC6gORAu0DmALxA58C8wOmAvYDrQL4A7QC+wO7Av0DwgL/A8oCAQTRAgIE2AIDBOACBQToAgYE7wIHBPcCCAT/AggEBwMJBA8DCQQPAwkEBwAAAPwCAADo+vAAAAAEAAAALQEBAAQAAADwAQIAIAAAACQDDgBZAukCgQL9ApoCHAO5Ah4D2QI5A7kCfAOHAq8DdALeA1gCzQNeAmgDRQI1Ay8CDQNZAukCWQLpAhYBAAAkA4kAsQLNAagC5wG1Ag8C2QLxAd0CxwH9As0BOgP+AVsDKAI9AzcCCQMzAtACTQKmAkgClwIyAogCOgKPAlcCyAJgAgYDVwL1AnsCtQJ2ApMCbgJyAl0CSAJ3AjoClgIzAmYCGAJkAgACmQIlAtkCLwLfAiwC7wIuAg8DDwLaAuMBugLjAbkC4wG1AuMBsgLkAa8C5AGrAuYBpgLmAaMC5wGgAucBnQLoAZoC6AGWAukBkgLrAY8C7AGLAu0BhgLuAYIC8AF9AvIBeALyAXUC8wFyAvMBcAL1AW0C9gFqAvcBZwL4AWQC+QFhAvoBXgL7AVsC/AFXAv0BVAL+AVECAAJOAgECSwIDAkgCBAJFAgYCQgIHAj4CCQI8AgoCOAIMAjUCDgIzAhACMAISAiwCFAIqAhYCJwIYAiQCGgIhAhwCHgIeAhsCIQIYAiMCFQIlAhMCJwIQAioCDQIuAggCNAIDAjYCAAI4Av0BOwL7AT4C+AFAAvYBQgL0AUUC8QFIAu8BSwLsAU0C6wFQAugBUwLmAVUC5AFYAuIBWwLgAV4C3wFhAtwBZALaAWcC2AFpAtcBbALVAW8C1AFyAtIBdQLRAXgCzwF7As4BfQLMAYACywGDAsoBhgLJAYkCyAGMAscBkQLFAZUCwwGaAsIBngLBAaECvwGkAr8BpwK+AaoCvgGuAr4BsQK/AbMCwAG1AsIBtQLFAbQCyQGyAswBsQLNAbECzQEqAAAAJAMTALUDkgLfA58C5gO1AhgEuQIuBPgCOwT7AhIEHwP9A1ID8gNXA9kDnAO4A6sDrAN2A7IDGgOjAwgDgwMGA3UDvwKbA5cCtQOSArUDkgKqAAAAJANTAKMDZgKnA4UCvQOOAtYDhgLZA3gC9QN5AgkEmQIEBKkCFwSaAgkEhQIGBG0CHQRtAjIEiQIvBJgCPASfAjwEngI7BJsCOgSXAjkEkwI4BJACNwSNAjYEiQI1BIYCNASCAjIEfgIxBHoCMAR2Ai4EcQIsBG0CKwRoAikEZAInBF8CJQRbAiMEVgIhBFICHwRNAh0ESQIaBEUCGARAAhUEPAIUBDgCEQQ0Ag8EMQIMBCwCCQQpAgYEJQIDBCECAQQeAv4DGgL7AxcC+AMUAvUDEALyAw0C7wMKAu0DBwLqAwQC5wMBAuUD/wHjA/0B3gP4AdoD9AHWA/AB0wPtAdAD6wHPA+kBzQPoAbMD7QG2AwgCswMPAr8DHgLFAxcCxQP6AdADAwLaAxUC0wMtAsMDNAK5AzACtgNGArkDXQLDA14CxQNoAqMDZgKjA2YCBwAAAPwCAACov7oAAAAEAAAALQECAAQAAADwAQEAOAIAACQDGgENAwMEDwN3BDQDdgRDA0MEkAMtBMMDUAT7Ay4E+QPzAyMExwNcBM8DhASQA2IEXwN5BA8DqwQHA6sEBAOrBAEDqwT/AqsE/AKrBPkCqwT2AqsE9AKrBPICqwTvAqsE7AKrBOoCqwTnAqsE4gKrBN0CqwTaAqsE1wKrBNUCqwTTAqsE0AKrBM0CqwTLAqsEyAKrBMMCqwS+AqsEuQKrBLQCeASlAmIEWAKFBCUCZATsASkE7wH9A8UBBASLAcUDYwGVA4YBRANvATwDPQEMAzsB8gJwAQ4DrgEPA64BEQOuARMDrgEWA64BGgOuAR4DrgEjA68BJgOvASgDrwErA68BLgOwATEDsAE0A7EBOAOxATsDsgE+A7IBQgOzAUUDtAFKA7UBTQO2AVEDtwFVA7gBWQO5AV0DuQFhA7oBZQO8AWoDvQFuA74BcgPAAXYDwQF7A8MBfwPEAYMDxgGIA8gBjAPKAZADzAGVA84BmQPQAZ4D0wGiA9UBpwPYAasD2gGvA90BswPgAbgD4gG8A+YBwAPpAcQD7AHIA+8BzAPzAdAD9wHUA/oB2AP+AdwDAgLgAwcC4wMKAuYDDALqAw8C7QMTAvADFQLzAxkC9gMcAvkDHwL7AyIC/QMmAgAEKQIDBCwCBQQwAgcEMwIKBDYCDAQ6Ag4EPQIQBEECEgREAhQESAIVBEsCFwRPAhkEUgIbBFYCHQRaAh4EXQIgBGECIQRlAiMEaAIkBGwCJgRwAicEcwIoBHcCKQR6AioEfQIrBIECLASFAi0EiAIuBIwCLwSQAjAEkwIxBJYCMQSaAjIEnQIzBKECNASkAjQEpwI1BKsCNQSuAjUEsQI2BLQCNgS4AjcEugI3BL4COATBAjgExAI4BMcCOQTKAjkEzQI5BNACOQTTAjoE1gI6BNkCOwTcAjoE3QI6BOACOgTjAjoE5wI5BOsCOATwAjgE8gI4BPUCNwT3AjcE+gI2BP0CNgQAAzUEAgM1BAYDNAQJAzQEDAMzBA8DMwQTAzIEFgMxBBoDMAQdAy8EIQMuBCQDLQQoAywELAMrBDADKgQzAykENwMnBDsDJgQ/AyQEQwMjBEcDIQRKAyAETwMeBFMDHARWAxoEWgMZBF4DFwRiAxUEZgMTBGoDEQRvAw4EcgMMBHYDCQR6AwcEfgMEBIIDAQSGA/4DiQP8A44D+QORA/YDlQPyA5kD7wOcA+wDoAPoA6QD5QOnA+IDqwPgA6sD3gOuA9wDrwPaA7ID1wO1A9QDuAPQA7oDzAO+A8cDwQPDA8UDwAPHA70DyQO7A8sDuAPNA7UDzwOyA9EDrwPTA6wD1gOoA9cDpQPZA6ED2wOeA90DmgPfA5YD4QOSA+MDjgPlA4oD5wOFA+kDgQPrA30D7AN4A+4DcwPwA24D8gNqA/QDZAP1A18D9wNaA/gDVQP5A08D+gNJA/wDRAP9Az4D/gM4A/8DMgMABCwDAQQmAwEEHwMCBBkDAgQTAwMEDQMDBA0DAwQHAAAA/AIAAP///wAAAAQAAAAtAQEABAAAAPABAgCEAAAAJANAACUAvAElALwBJwC8ASkAvAEuALwBMAC8ATIAvAE1ALwBOQC9ATwAvQFAAL0BRAC+AUgAvgFMAL4BUAC/AVUAvwFaAMABXwDAAWQAwAFqAMEBbwDCAXUAwgF7AMMBgQDDAYcAxAGNAMUBlADGAZoAxgGhAMgBpwDIAa4AyQG0AMoBuwDLAcIAzAHJAM0B0ADOAdcA0AHeANEB5QDSAe0A1AH0ANUB+wDXAQIB2AEJAdkBEQHbARcB3QEfAd4BJgHgAS0B4gEzAeQBOwHmAUIB6AFJAeoBTwHsAVYB7gFdAfABYwHzAWkB9gFvAfgBdgH7AXwB/gEAABoCJQC8ASUAvAEHAAAA/AIAAAAAAAAAAAQAAAAtAQIABAAAAPABAQCUAwAAJAPIAdkCAwLXAgQC1AIFAtECBgLPAgcCzAIIAskCCgLGAgsCwwIMAsACDgK8Ag8CugIRArcCEgKzAhQCsAIVAq4CFwKrAhkCpwIaAqQCHAKiAh0CnwIfApoCIQKWAiQCkgImApACKAKOAikCjgIpAjkCFQI7AhcCPQIaAkECHgJEAiECSQImAksCKQJOAisCUQIuAlUCMQJXAjMCWgI1Al4COAJhAjsCZAI9AmgCPwJrAkECcAJEAnMCRgJ3AkgCegJJAn4CSgKCAksChgJNAooCTQKOAk4CkgJOApYCTgKaAk4CnQJOAqECTQKlAk0CqQJNAq0CTAKwAksCtAJLArcCSgK7AkkCvgJIAsECSALEAkcCyAJHAsoCRQLNAkUCzwJDAtICQwLWAkEC2gJAAt0CPgLgAj4C4QI9AuICPQIBA44CAAONAv8CjQL8Ao0C+QKNAvcCjQL1Ao0C8gKNAvACjgLtAo4C6gKOAucCjwLjApAC3wKQAtsCkALXApEC0wKSAs4CkwLJApUCxAKWAr8CmAK8ApgCugKZArcCmgK0ApoCsAKbAq4CnAKrAp4CqAKfAqQCoAKhAqECngKiApsCpAKYAqUClAKmApECqAKOAqoCigKrAocCrQKDAq4CgAKwAnwCsgJ5ArQCdQK3AnICuQJuArwCawK+AmcCwQJkAsQCYQLHAl4CygJaAs0CVwLRAlQC1AJRAtgCTQLbAksC3wJIAuICRQLmAkIC6gI/Au4CPALxAjkC9QI3AvgCNAL9AjECAAMuAgQDLAIIAyoCDAMnAg8DJQITAyMCFgMhAhoDHgIdAxwCIQMaAiQDGQIoAxcCKwMVAi4DEwIxAxICNAMQAjcDDwI6Aw4CPQMNAkADCgJEAwgCSQMHAk0DBgJQAwUCUwMFAlQDBQJVAwYCVgMLAlQDEAJSAxUCUAMaAk4DHwJMAyQCSQMpAkcDLgJFAzICQgM3Aj8DOwI8A0ACOQNEAjYDSAIzA0wCMANRAiwDVQIpA1kCJQNeAiADYgIdA2YCGANqAhQDbgIPA3MCCgN0AggDdgIFA3gCAgN7AgADfAL9An4C+wKAAvgCgwL2AoUC8wKHAvACiQLtAosC6gKNAucCkALkApEC4QKUAt4CEwPTAhMD0wIVA9YCFQPXAhYD2gIYA90CGQPgAhsD4wIcA+YCHgPqAiAD7gIiA/ICJAP2AicD+wIpAwADLAMEAy4DCQMxAw0DNAMSAzcDFwM6AxwDPQMgA0EDJQNEAykDRwMtA0oDMQNOAzUDUQM5A1UDPQNYAz8DXANDA18DRQNiA0cDZQNJA2kDTANtA04DcANQA3QDUgN3A1QDewNWA38DWAOCA1kDhgNbA4kDXAONA14DkANfA5QDYQOYA2IDnANjA58DZAOjA2YDpgNmA6oDaAOuA2gDsgNpA7UDagO4A2sDvANrA78DbAPDA20DxgNtA8kDbgPNA28D0ANvA9MDbwPWA28D2gNwA9wDcAPfA3AD4gNwA+UDcAPnA3AD6gNwA+0DcAPvA3AD9ANwA/kDcQP9A3ADAQRwAwMEcAMHBHADCwRvAw0EbwMLBGwDCQRqAwYEZwMEBGUDAgRiA/8DXwP8A1wD+QNaA/YDVwPzA1QD8ANRA+0DTwPpA0wD5QNJA+IDRwPeA0UD2gNCA9YDPwPRAz0DzQM6A8gDOAPEAzYDvwMzA7sDMgO4AzADtQMvA7IDLgOwAy0DqwMrA6YDKgOjAykDoAMoA54DJwObAycDmAMmA5UDJQOTAyQDkAMkA3UDygJwA5kCfwOYAn4DkgJ9A44CewOJAnoDhQJ5A4ACdwN7AnYDdwJ1A3MCcwNvAnIDagJwA2cCbgNjAm0DXwJrA1wCagNYAmgDVQJmA1ICZQNPAmMDTAJiA0kCXwNFAl0DQQJaAz4CWQM7AlkDOgKPAz8C4wOPAuIDjgLiA4sC4QOJAuEDhwLgA4UC4AOCAt8DfwLeA3sC3QN4AtwDdQLbA3EC2gNtAtgDaALXA2UC1ANgAtIDWwLQA1YCzgNSAssDTQLIA0gCxQNEAsIDPwK+AzsCuwM2ArcDMgKzAy4CrgMqAqoDJQKlAyECoAMfAp0DHQKaAxsClwMZApQDFwKSAxYCjwMVAowDEwKKAxIChwMRAoQDDwKBAw4CfwMNAnkDCwJ1AwkCcgMIAm8DBwJtAwYCagMFAmUDBAJhAwICWwMBAlcDAAJTA/8BTwP+AUoD/QFGA/wBQgP7AT8D+wE7A/sBOAP6ATUD+gEzA/oBLgP6ASsD+gEpA/oBKQP6ASgD+gEmA/oBIwP6AR8D+gEcA/oBGgP6ARcD+gEUA/oBEQP6AQ4D+wELA/sBCQP8AQUD/AECA/wB/gL8AfsC/QH3Av0B9AL9AfEC/gHuAv8B6wL/AegC/wHlAgAC4gIBAt0CAgLZAgMC2QIDAmIAAAAkAy8ALgNMAhgD9AEkA/UBIQPyASAD8AEeA+8BHQPuARsD7AEZA+wBFwPqARUD6AEoA+wBJgPnASID5AEfA+IBHAPgARgD3gEVA90BKQPfAScD3AEkA9kBIAPWARwD0wEZA9IBFwPQARQDzwESA88BDwPOAQwDzgEJA84BBwPOAQQDzAECA8sB/wLKAf0CygH6AskB9wLKAfUCywH0AswB/ALSAfUC6wH4AuwB9wL5Af8C+QH9AkgCLgNMAi4DTAIUAAAAJAMIAMYDbwLXA5cC5wObAuwDggLkA4EC2QN2AsYDbwLGA28CGAAAACQDCgDuA3YC3gN1AtwDuQIEBKwC7gOrAuMDrALmA3wC9wN8Au4DdgLuA3YCcgAAACQDNwD6A0ICRwRXAkcEWAJIBFoCSARcAkkEXgJJBGACSgRkAkoEZwJLBGoCSwRuAkwEcgJNBHYCTgR7Ak4EfQJPBH8CTwSCAlAEhQJQBIcCUQSKAlEEjQJRBJACUQSSAlIElQJSBJgCUgSbAlIEngJSBKECUgSkAlMEpgJTBKkCUwStAlMEsAJUBLMCVAS2AlQEuQJUBLwCVATAAlQEwwJUBMYCVATJAlQEzQJTBM8CUwTTAlME1gJTBNoCUwTdAlME4AJSBOMCUgTnAgYE8QLuA+wC6QNIAvoDQgL6A0ICBwAAAPwCAAD///8AAAAEAAAALQEBAAQAAADwAQIAEgAAACQDBwD9AgICCQMyAh4DMAIdA/8BCQMFAv0CAgL9AgICBwAAAPwCAACoSj0AAAAEAAAALQECAAQAAADwAQEAGgAAACQDCwAJAwoCBgMVAgoDGwIJAzMCGwNtAh4DMQIOAxoCEgMVAgwDCQIJAwoCCQMKAgcAAAD8AgAAQn2KAAAABAAAAC0BAQAEAAAA8AECANwAAAAkA2wA/QKTAvwCkwL5ApMC9gKTAvQClALxApQC7gKVAusClQLnApYC4gKXAt8CmALaApgC1gKZAtECmgLMApsCyQKbAscCnALEApwCwgKdAr8CngK8Ap4CugKfArcCoAK0AqACsgKhAq8CogKtAqMCpwKkAqMCpQKeAqcCmQKoApQCqgKQAqwCjAKuAogCsAKFArICggK0An4CtgJ7ArgCeAK6AnUCvAJyAr4CcALAAm0CwgJrAsQCZwLHAmMCywJfAs4CXQLSAlkC1gJVAtkCUgLeAk8C4gJLAucCRwLsAkQC7wJCAvICPwL1Aj0C+AJLAu4CTQLrAlAC6AJTAuQCVgLhAloC3QJeAtkCYgLWAmcC0gJrAs4CcALKAnQCxgJ6AsMCfgLAAoMCvQKIAroCjQK5ApECtgKWArQCmwKxAqACsAKlAq4CqgKtAq8CqwK0AqoCuQKoAr4CpwLCAqUCyAKlAswCpALRAqMC1gKiAtoCogLeAqEC4gKgAuYCnwLqAp8C7QKeAvECngL0Ap4C9wKeAvkCnQL8Ap0C/gKdAv8CnQICA50CAwOdAv0CkwL9ApMCBwAAAPwCAAAAAAAAAAAEAAAALQECAAQAAADwAQEAMAAAACQDFgAGAkUDBQJDAwECPwP+ATwD/AE6A/gBNwP1ATYD9QE3A/YBPAP2AT4D+AFCA/kBRgP7AUsD/AFPA/4BUwMAAlUDAQJYAwICWwMDAlwDDQJSAwYCRQMGAkUD/gIAACQDfQF6BJADfASRA38ElAODBJcDhgSbA4kEnQONBKEDkASlA5QEqQOXBKwDmgSvA50EsgOgBLUDowS5A6UEuwPmBMED5QTBA+MEwgPhBMMD3gTEA9oExgPVBMgD0ATLA8sEzgPIBM4DxQTPA8IE0APABNEDvATSA7kE0wO2BNQDtATVA7AE1QOtBNUDqgTVA6cE1gOkBNUDoQTVA54E1QOcBNUDmQTUA5YE0wOTBNIDkATRA4sEzgOHBMwDggTJA30ExwN5BMQDdgTCA3EEvwNvBLwDbAS6A2oEuQNmBLYDZgS1AzwE5wM9BOcDQQToA0QE6QNHBOsDSwTsA1AE7wNSBPADVQTxA1gE8wNbBPUDXgT2A2EE+ANkBPoDaAT9A2sE/wNvBAIEcgQFBHcECAR6BAsEfwQOBIMEEQSIBBUEjAQZBI8EHQSTBCEElwQnBJgEKQSaBCwEmwQvBJ0EMgSfBDQEoAQ3BKIEOgSjBD4EpARABKYEQwSnBEYEqARJBKkETASrBE8ErARSBK0EVgStBFkErwRcBK8EXwSxBGMEsQRmBLIEaQSzBGwEtARwBLUEcgS1BHUEtgR4BLYEewS2BH4EtwSBBLcEhAS4BIYEuQSLBLoEkAS7BJUEvASaBLwEnQS8BKEEvQSkBL0EpwS+BKsEvgSsBLoEqQS3BKYEtASjBLEEoASuBJ0EqwSaBKgEmASmBJUEowSRBKAEjwSeBIwEnASJBJkEhgSXBIIElQR/BJMEfASRBHgEjwR1BI0EcQSLBG4EiQRqBIcEZgSFBGIEhAReBIIEWgSBBFYEfwRSBH0ETQR8BEgEegRDBHkEPgR4BDoEIAQTBB8EEwQfBBUEHQQWBBwEGQQaBBwEGQQgBBcEJQQVBCoEFAQsBBIELwQRBDIEEAQ0BA4ENwQNBDoEDAQ9BAsEQAQJBEMEBwRGBAYESQQEBEwEAwRPBAIEUgQABFUE/wNYBPsDXQT4A2IE9ANnBPADawTsA28E5wNzBOMDdgTeA3oE2wN7BNkDfQTWA34E0wOABNADgQTOA4IEywOEBMkDhQTGA4YEwwOHBMADiAS+A4kEuwOKBLkDiwS2A4wEswOOBLEDjgSuA48EqwOPBKgDkASlA5AEowORBKADkgSeA5MEmAOUBJQDlQSPA5YEiwOXBIcDlwSCA5gEfwOYBHwDmQR4A5kEdgOaBHQDmgRzA5sEcwOXBHQDlAR2A5AEegOLBH0DhgSCA4EEhAN+BIcDfASKA3oEjQN3BJADdASUA3EElwNvBJsDbASeA2kEogNnBKcDZQSrA2MErwNgBLMDXQS4A1sEvQNaBMEDVwTGA1UEyQNUBMwDVATPA1ME0QNSBNEDUATRA0wE0QNKBNIDSATSA0UE0wNDBNMDPwTTAz0E1AM5BNQDNgTUAzIE1QMvBNUDKwTWAygE1gMjBNYDIATXAxwE1wMYBNcDFQTYAxEE2AMNBNkDCwTZAwcE2QMEBNoDAQTaA/8D2gP8A9sD+QPbA/cD3AP2A9wD8QPdA+0D3gPoA+AD5APhA98D4wPbA+UD1wPnA9QD4gPRA+MDzgPlA8oD5gPHA+gDxAPqA8ED7QO+A+8DvAPxA7kD8gO3A/UDtAP3A7ED+QOvA/0DqwMBBKcDBASjAwgEoAMLBJ0DDQSbAxEEmQMTBJgD7AOPA54DswOeA7IDngOwA58DrgOiA6oDpAOmA6cDogOrA5wDsAOYA7IDlQO0A5IDtgOPA7kDjQO8A4oDvwOHA8IDhQPGA4IDyQN/A80DfQPRA3sD1QN5A9kDdwPdA3YD4gN0A+cDcwPrA3ID7wNxA/QDcAP5A3AD/QNvAwEEbgMFBG4DCgRuAw0EbgMRBG4DFQRuAxkEbgMcBG4DIARvAyMEbwMnBHADKgRwAywEcAMvBHADMgRxAzcEcgM7BHMDPgR0A0AEdQNCBHUDQwR2A0QEdgNGBHYDSQR4A0wEeQNQBHsDVAR8A1kEfgNdBIADYgSCA2cEhANsBIYDcASIA3MEiwN3BI0DegSQA3oEkANKAAAAJAMjACwErwNQBHQDSQRyA0wEcANPBHADUgRvA1YEbgNHBGsDSQRpA00EaANPBGcDUgRmA1QEZgNYBGYDSQRiA0sEYANOBF4DUQRdA1UEXANYBFwDXARcA2AEXANlBF4DaQRcA20EXQNwBF4DcwRhA20EZANrBHcDaAR2A2cEgANhBH8DTwS2AywErwMsBK8DFAAAACQDCAC5A6MDowO8A5cDuwOaA6kDoAOpA6sDpAO5A6MDuQOjAxgAAAAkAwoAmwOeA6cDoQOZA9MDfwO/A48DxAOXA8cDoAOlA5QDogObA54DmwOeA0oAAAAkAyMAngN3A14DdANeA3QDXQN2A1sDeQNZA3wDWAN+A1cDgANWA4MDVQOGA1MDiANSA4sDUAOPA08DkgNOA5UDTAOZA0sDnANJA6EDSAOlA0YDqQNFA60DRAOyA0IDtgNBA7oDPwO/Az4DwwM8A8gDOwPNAzsD0gM6A9cDbgPxA4AD8gOpA38DngN3A54DdwMHAAAA/AIAAP///wAAAAQAAAAtAQEABAAAAPABAgASAAAAJAMHAGAEhgNNBKQDPwSeA0oEfANYBIUDYASGA2AEhgMHAAAA/AIAAKhKPQAAAAQAAAAtAQIABAAAAPABAQAaAAAAJAMLAFYEiQNWBJEDUASUA00EpQMzBMoDPgSgA04EkgNOBI8DVQSGA1YEiQNWBIkDBwAAAPwCAACeqJ4AAAAEAAAALQEBAAQAAADwAQIAtgAAACQDWQA+BOwDPwTsA0AE7ANDBO0DRwTwA0sE8gNRBPUDUwT3A1YE+ANaBPoDXQT8A2AE/gNjBAAEZgQBBGoEBARtBAYEcAQIBHMECgR3BAwEeQQOBHwEEQR/BBMEggQVBIQEFwSGBBoEiQQcBIsEHwSOBCMEkQQnBJQEKwSXBC8EmAQzBJoENgScBDoEngQ+BJ8EQQShBEUEogRJBKMETQSlBFIEpwRWBKgEWQSpBFwEqwReBKwEYQSkBFMEogRRBKEETgSgBEsEngRIBJwERASaBEEEmAQ+BJcEOgSVBDYEkwQzBJAELwSOBCwEjAQpBIkEJgSHBCMEhAQgBIEEHgR+BBsEewQYBHgEFgR1BBMEcgQRBG8EDwRsBA0EaAQLBGUECQRhBAYEXgQFBFsEAwRYBAEEVQQABFIE/wNQBP0DTQT7A0oE+gNIBPkDQwT3Az8E9QM8BPQDOQTzAzcE8gM+BOwDPgTsAwcAAAD8AgAAAAAAAAAABAAAAC0BAgAEAAAA8AEBADAAAAAkAxYAwgSjBMMEogTIBJ8EygSeBMwEnQTPBJwE0gScBNIEnQTQBKAEzwShBM0EpATLBKYEyQSqBMYErATFBK4EwwSvBMIEsQTABLMEwAS0BLsEqgTCBKMEwgSjBB4AAAAkAw0AfQOYBIIDsQSBA7AEfwOuBHsDqwR3A6cEcgOjBG4DnwRrA5sEagOZBHMDlQR9A5gEfQOYBDwAAAAkAxwA2gTCA9sEwQPdBL4D4AS7A+MEuQPlBLgD5wS3A+oEtwPtBLkD8AS5A/IEugPzBLsD9AS8A/IEvAPwBLwD7AS9A+oEvgPnBMAD5wTCA+cEwgPrBMMD7wTCA/EEwwPxBMQD8QTFA+MExgPaBMID2gTCAwcAAAD8AgAAnqieAAAABAAAAC0BAQAEAAAA8AECALYAAAAkA1kAEgQKBBIECgQRBAwEEQQOBBAEEgQPBBUEDgQaBA0EHAQNBB8EDQQiBAwEJQQLBCgECgQqBAkELQQIBDAEBwQzBAYENgQFBDkEBAQ9BAMEPwQCBEIEAQRFBAAESAT+A0oE/QNNBPsDUAT6A1IE9wNXBPMDXATvA2AE7ANkBOgDZwTlA2sE4QNuBN4DcQTaA3QE1gN3BNIDeQTPA3sEywN9BMcDgATDA4IEvwOEBMADgwTFA4EExwN+BMoDfATOA3oE0QN3BNUDcwTZA28E3QNrBOMDZwTlA2QE5wNhBOkDXgTsA1wE7gNZBO8DVgTxA1ME9ANQBPUDTAT3A0kE+ANFBPkDQgT7Az4E/AM7BP4DNwT/AzQEAAQwBAEELAQCBCkEAwQmBAQEIgQFBB8EBgQcBAcEGQQIBBYECAQTBAkEEAQKBA4ECwQJBAwEBQQMBAIEDQQABA0E/gMNBP4DEgQKBBIECgSgAAAAJANOAEQEegNDBHoDQgR5Az8EeQM9BHgDOgR3AzYEdgMyBHUDLQR1AysEdAMoBHQDJQRzAyMEcwMgBHMDHQRyAxoEcgMYBHIDFQRyAxIEcgMPBHIDDQRyAwoEcgMHBHMDBARzAwIEdAP/A3QD/AN1A/oDdQP4A3YD9AN3A/ADeAPtA3kD6gN6A+cDewPlA3wD4QN9A94DfwPbA4AD2AOCA9QDhAPRA4YDzQOJA8gDjAPUA4cD2AOGA98DgwPiA4ID5QOBA+cDgAPqA38D7QN+A+8DfQPyA30D9QN8A/gDfAP7A3sD/gN6AwEEegMDBHkDBgR5AwkEeQMOBHkDEwR5AxUEeQMYBHkDGwR5Ax4EegMiBHoDJwR7AysEfAMwBHwDNAR9AzcEfgM6BH4DPgR/A0MEgQNEBHoDRAR6AwcAAAD8AgAA5vL/AAAABAAAAC0BAgAEAAAA8AEBAAgBAAAkA4IAYQHHA2UBxwNpAcYDbQHGA3ABxQN0AcQDeAHDA3sBwgN/AcEDgwG/A4YBvQOJAbsDjAG5A48BtwOSAbUDlQGyA5gBsAOaAa0DnAGqA58BpwOhAaUDowGhA6UBngOmAZsDqAGYA6kBlAOrAZADrAGNA6wBiQOtAYUDrQGCA64BfQOuAXoDrgF2A60BcgOtAW4DrAFqA6wBZgOrAWMDqQFfA6gBXAOmAVgDpQFVA6MBUgOhAU8DnwFMA5wBSQOaAUcDmAFEA5UBQQOSAT8DjwE9A4wBOwOJATgDhgE3A4MBNQN/ATQDewEzA3gBMQN0ATADcAEwA20BLwNpAS4DZQEuA2EBLgNdAS4DWQEuA1UBLwNRATADTgEwA0oBMQNHATMDQwE0Az8BNQM8ATcDOQE4AzYBOwMzAT0DMAE/Ay4BQQMrAUQDKQFHAyYBSQMkAUwDIgFPAyABUgMeAVUDHQFYAxsBXAMaAV8DGAFjAxcBZgMXAWoDFgFuAxYBcgMWAXYDFgF6AxYBfQMWAYIDFgGFAxcBiQMXAY0DGAGQAxoBlAMbAZgDHQGbAx4BngMgAaEDIgGlAyQBpwMmAaoDKQGtAysBsAMuAbIDMAG1AzMBtwM2AbkDOQG7AzwBvQM/Ab8DQwHBA0cBwgNKAcMDTgHEA1EBxQNVAcYDWQHGA10BxwNhAccDYQHHAwcAAAD8AgAAgICAAAAABAAAAC0BAQAEAAAA8AECADABAAAkA5YAQgFJAz8BSgM9AU0DOwFPAzgBUgM0AVYDMwFYAxwBWwMeAVwDIQFdAyUBXwMpAWADLQFhAzIBYQM2AWEDOgFgAz0BXgNAAVwDQwFbA0cBWANIAVcDVwFoA1YBaANVAWgDUwFpA1ABawNMAW0DRwFwA0UBcQNCAXMDPwF2Az0BeQM6AXwDNwF/AzQBgwMzAYcDMQGLAzABkAMuAZQDLQGZAywBnAMrAaEDKgGlAyoBqAMqAaoDKgGtAyoBrgMqAa8DLgGqAzIBpgM1AaIDOQGdAzoBmwM7AZgDPQGVAz4BkwM/AZADQAGMA0EBiQNDAYYDYQF4A2IBegNjAXwDZQGAA2cBgwNpAYcDawGLA24BkANvAZIDcgGWA3UBmQN5AZsDfAGdA4ABnwOEAaEDiAGjA4sBowOPAaQDkgGlA5YBpgOYAaYDmwGmA50BpwOfAacDngGlA5wBogOZAZ4DlgGbA5MBmQOQAZcDjgGVA4sBkwOIAZEDhAGQA4EBjwN+AY4DfQGLA3wBiAN8AYQDfAF/A3sBfAN7AXkDewF3A3sBdAN6AXADegFuA3kBagN4AWcDdwFkA3YBYQN4AWADdQFcA3IBWANvAVQDbAFRA2cBTQNmAUwDdQFJA5ABVgOPAVUDjgFTA4wBTwOJAUwDhQFIA4EBRAN+AUMDewFBA3kBQAN2AT8DcgE+A28BPQNsAT0DaQE9A2YBPQNjAT0DYQE9A18BPgNaAT8DVwE/A1UBQANVAUADVAFAA1IBQQNPAUIDTQFDA0kBRANGAUYDQwFIA0IBSQNCAUkDMgAAACQDFwBdAVQDUQE/A1QBPwNRAT4DTwE9A1QBPANRATsDTgE7A1MBOgNRATgDTwE3A0wBNwNJATcDRgE3A0QBOQNGAToDRwFAA0gBQANIAUQDSwFDA1EBVwNdAVQDXQFUAxQAAAAkAwgAhQFQA44BWAOSAVgDkQFSA44BUwOLAVADhQFQA4UBUAMYAAAAJAMKAJEBTwONAU8DkgFhA5sBWwOWAVwDkgFdA44BUgOTAU8DkQFPA5EBTwMqAAAAJAMTAI4BQAOkAT8DpAFAA6UBQgOnAUUDqgFKA6sBTAOsAU8DrQFSA64BVQOvAVgDsQFbA7IBXgOzAWIDoQFrA5oBawOLAUQDjgFAA44BQAMSAAAAJAMHAEsBRgNRAVADVwFOA1MBQwNOAUUDSwFGA0sBRgMaAAAAJAMLAE4BRwNPAUkDUQFLA1EBUgNbAV4DVwFPA1EBSwNRAUkDTwFGA04BRwNOAUcDSAAAACQDIgBXAWkDVgFpA1MBawNPAW0DSwFwA0YBcgNCAXYDPQF5AzsBfAM4AX8DNgGCAzQBhAM0AYcDMwGJAzIBjAMxAY8DMAGTAzIBjwMzAYsDNwGGAzgBgwM6AYADPAF+Az4BfANCAXgDRwF1A0sBcgNQAXADUwFuA1cBbANZAWsDWgFrA1cBaQNXAWkDIAAAACQDDgApAaoDKAGpAycBqQMlAagDIwGnAyMBqQMlAa0DJwGuAykBrwMpAbADKQGwAysBrQMpAaoDKQGqAxYAAAAkAwkAmwGmA5kBrwOaAa8DnQGsA6ABqQOiAaYDnwGlA5sBpgObAaYDKAAAACQDEgAgAVsDHwFaAx4BWAMbAVcDGQFXAxcBWAMXAVkDGAFZAxoBWQMbAVoDGwFbAxsBWwMaAVwDGAFcAxgBXAMcAV0DIAFbAyABWwMHAAAA/AIAAEJ9igAAAAQAAAAtAQIABAAAAPABAQDAAAAAJANeAB0DxgIdA8cCHQPJAh0DywIeA80CHwPPAiAD0gIhA9QCIgPXAiQD2gImA98CJwPiAikD5gIrA+sCLQPvAi8D8wIxA/cCMwP8AjYDAAM5AwUDPAMKAz8DDwNCAxQDRQMYA0gDHgNMAyIDTwMnA1MDKwNXAzADWwM0A18DOQNjAzwDZwM/A2wDQgNwA0UDdQNIA3kDSgN+A00DgwNPA4cDUQOLA1IDjgNTA5IDVQOUA1UDlgNWA5cDVwOYA1cDlwNXA5YDVgOUA1QDkgNTA44DUAOLA00DhwNJA4MDRwN/A0MDegM/A3YDOwNyAzgDbQM0A2oDMQNmAy4DYwMrA2EDKQNfAycDXQMkA1sDIgNZAx8DVgMbA1MDGANRAxUDTgMQA0sDDANIAwgDRQMEA0IDAAM/A/sCPAP3AjoD8wI2A+4CMwPqAjED5gIuA+ECKwPdAikD2gInA9cCJQPUAiMD0AIhA84CIAPLAh4DygIdA8cCHQPGAh0DxgIHAAAA/AIAAKi/ugAAAAQAAAAtAQEABAAAAPABAgAaAgAAJAMLARIDrgEPAzoB6gI7AdsCbwGNAoQBWwJiASICggElAr4B+wHrAcAB4gGZASECvAFSAqUBnAJyAaoCcQGuAnEBsgJwAbcCcAG8AnABwQJwAcYCcAHJAnABzAJwAc4CcAHRAnAB1AJwAdcCcAHZAnAB3AJwAd8CcAHiAnAB5QJwAegCcAHrAnAB7QJwAfACcQHzAnEB9gJxAfkCcgH8AnIB/wKlAQ0DugFbA5gBjAO4AcYD9AHDAyEC7AMYAigEWAJPBIcCLQTYAkQE4QJ0BA8DdwQlA0cEDgMDBA0DAwQMAwMECgMDBAgDAwQEAwIEAAMCBPwCAgT4AgIE9QIBBPICAQTvAgEE7AIABOkCAATmAv8D4wL/A+AC/wPcAv4D2QL9A9UC/APSAvsDzgL6A8oC+gPGAvkDwgL4A74C9wO6AvYDtgL1A7EC9AOtAvIDqQLxA6QC7wOhAu4DnALsA5gC6gOTAugDjwLnA4sC5AOHAuIDggLhA34C3wN5AtwDdQLZA3EC1wNsAtQDaALRA2QCzgNfAswDXALJA1cCxQNTAsIDTwK/A0sCuwNHArgDRAK0A0ACsAM9AqwDOwKrAzgCqAM2AqYDNAKkAzECoQMvAp8DKwKbAygClwMkApIDIQKOAx8CiwMdAogDGwKGAxkCgwMXAoADFQJ9AxMCegMRAncDDwJzAw0CcAMLAmwDCQJoAwYCZQMFAmEDAwJcAwECWQP/AVQD/QFQA/sBSwP6AUcD+AFCA/YBPgP0ATkD8wE0A/EBLwPwASoD7gElA+0BHwPrARoD6gEUA+kBDgPoAQkD5wEDA+YB/QLlAfYC5QHxAuQB6gLjAeQC4wHdAuMB1wLjAdUC4wHTAuMBzwLjAc0C4wHIAuQBxALkAb8C5QG6AuUBtwLmAbQC5gGxAucBrgLnAasC6AGnAugBpALpAaEC6QGdAuoBmgLrAZYC7AGTAu0BjwLuAYsC7wGHAvABhALxAYAC8gF8AvMBeAL0AXQC9gFwAvcBbAL5AWgC+wFkAvwBYAL+AVwCAAJXAgICUwIEAk8CBgJLAggCRwILAkMCDQI/Ag8COwIRAjYCFAIzAhcCLgIZAioCHAInAiACIwIjAh8CJQIbAikCFwItAhQCMAIQAjQCDAI3AgkCPAIGAjwCBAI/AgICQAIAAkMC/gFFAvsBSQL4AUsC9QFQAvEBVALuAVkC6wFbAugBXgLmAWAC5AFkAuIBZwLgAWkC3wFtAtwBcQLbAXMC2AF3AtcBegLUAX4C0gGCAtABhgLOAYoCzAGOAssBkgLIAZYCxgGbAsQBnwLDAaQCwQGpAsABrgK+AbMCvQG4ArsBvQK5AcICuAHIArcBzQK1AdMCtAHYArMB3wKyAeQCsQHqArAB8AKvAfcCrwH9Aq4BBAOuAQoDrgESA64BEgOuAQcAAAD8AgAAAAAAAAAABAAAAC0BAgAEAAAA8AEBAEgAAAAkAyIATgIaAkwCGAJKAhUCRgISAkMCDwJAAgsCPAIJAjcCBwIzAgcCMAIHAi4CBwIsAgcCKwIIAioCCAIqAgkCLQIMAjECDwIyAhACNQISAjYCFAI4AhcCOAIXAjcCFwI2AhgCNAIYAjACFgItAhUCLAIUAisCFQIpAhYCKgIXAj4CIAJOAhoCTgIaAgcAAAD8AgAAQn2KAAAABAAAAC0BAQAEAAAA8AECAIoAAAAkA0MAZAIlAo4CMAKPAi8CkQIuApMCLAKYAioCmwIoAp0CJwKgAiUCowIkAqYCIgKqAiACrQIfArECHQK0AhsCuAIZArsCFwK/AhUCwgIUAsYCEgLJAhECzQIPAtACDgLTAgwC1gILAtkCCgLhAggC3QILAtkCDwLXAhAC1QISAtICFALPAhYCzAIYAskCGgLGAhwCxAIfAsACIAK9AiICuQIkArYCJwKyAikCrwIqAqwCLAKpAi4CpgIvAqICMQKfAjICnAIzApoCNAKXAjQClAI1ApMCNQKOAjUCigI0AoYCNAKBAjMCfQIyAnkCMAJ1Ai8CcwItAm8CKwJsAioCaQIpAmgCKAJkAiUCZAIlAgcAAAD8AgAA////AAAABAAAAC0BAgAEAAAA8AEBABAAAAAkAwYASwIZAlUCHgJPAicCQwIeAksCGQJLAhkCEAAAACQDBgDTA2gC1wN1AtADeQLFA24C0wNoAtMDaAIHAAAA/AIAAEJ9igAAAAQAAAAtAQEABAAAAPABAgBiAAAAJAMvAEoDCAKCAx4CyANVAsgDVALHA1ICxgNQAsQDTgLAA0oCvQNGArkDQQK1Az0CsAM4AqsDMwKoAzACpQMuAqIDKwKgAyoCnQMnApoDJQKXAyIClAMgApIDHwKPAx0CjAMbAokDGgKGAxgCgwMXAoADFQJ+AxUCewMTAngDEgJ1AxECcwMQAnADDwJtAw4CagMNAmgDDQJjAwsCXgMLAlkDCgJWAwkCUgMJAk8DCQJNAwgCSwMIAkoDCAJKAwgCAwAAAAAA"));
                    }

                    document.MainDocumentPart.Document.Body.Append(
                        new Paragraph(
                                new Run(
                                    new RunProperties(
                                        new NoProof()),
                                    new w.Drawing(
                                        new wp.Inline(
                                            new wp.Extent() { Cx = 2145665L, Cy = 2177415L },
                                            new wp.EffectExtent() { LeftEdge = 19050L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
                                            new wp.DocProperties() { Id = 1U, Name = "Picture 1", Description = "C:\\Program Files (x86)\\Microsoft Office\\MEDIA\\CAGCAT10\\j0149481.wmf" },
                                            new wp.NonVisualGraphicFrameDrawingProperties(
                                                new a.GraphicFrameLocks() { NoChangeAspect = true }),
                                            new a.Graphic(
                                                new a.GraphicData(
                                                    new pic.Picture(
                                                        new pic.NonVisualPictureProperties(
                                                            new pic.NonVisualDrawingProperties() { Id = 0U, Name = "Picture 1", Description = "wmf" },
                                                            new pic.NonVisualPictureDrawingProperties(
                                                                new a.PictureLocks() { NoChangeAspect = true, NoChangeArrowheads = true })),
                                                        new pic.BlipFill(
                                                            new a.Blip() { Embed = "rId6", CompressionState = a.BlipCompressionValues.Print },
                                                            new a.SourceRectangle(),
                                                            new a.Stretch(
                                                                new a.FillRectangle())),
                                                        new pic.ShapeProperties(
                                                            new a.Transform2D(
                                                                new a.Offset() { X = 0L, Y = 0L },
                                                                new a.Extents() { Cx = 2145665L, Cy = 2177415L }),
                                                            new a.PresetGeometry(
                                                                new a.AdjustValueList())
                                                            { Preset = a.ShapeTypeValues.Rectangle },
                                                            new a.NoFill(),
                                                            new a.Outline(
                                                                new a.NoFill(),
                                                                new a.Miter() { Limit = 800000 },
                                                                new a.HeadEnd(),
                                                                new a.TailEnd())
                                                            { Width = 9525 })
                                                        { BlackWhiteMode = a.BlackWhiteModeValues.Auto }))
                                                { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }))
                                        { DistanceFromTop = 0U, DistanceFromBottom = 0U, DistanceFromLeft = 0U, DistanceFromRight = 0U }))));
                }

                // validate created
                using (var document = WordprocessingDocument.Open(stream, false))
                {
                    var firstText = document.MainDocumentPart.Document.Descendants<Text>().First();
                    Assert.Equal("Hello World", firstText.Text);
                    Assert.True(document.MainDocumentPart.Document.Descendants<w.Drawing>().Count() == 1, "Drawing isn't added to main part.");
                    Assert.True(document.MainDocumentPart.GetPartById("rId6") is ImagePart);
                }
            }
        }

        /// <summary>
        /// AutoSaveTestPptx.
        /// </summary>
        [Fact]
        public void AutoSaveTestPptx()
        {
            // Change something in the master part.
            var textCount = 0;

            using (var stream = GetStream(TestFiles.Autosave, true))
            {
                using (var doc = PresentationDocument.Open(stream, true))
                {
                    var slide1 = doc.PresentationPart.GetPartById("rId2"); // Get part slide1.xml
                    var slideLayout1 = slide1.GetPartById("rId1"); // Get part slideLayout1.xml
                    var slideMaster1 = slideLayout1.GetPartById("rId1"); // Get slideMaster1.xml
                    Assert.Equal(typeof(SlideMasterPart), slideMaster1.GetType());

                    // Change a text "5/7/2009" to be "5/9/2009"
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/7/2009");
                    foreach (var text in texts)
                    {
                        text.Text = "5/9/2009";
                        textCount++;
                    }
                }

                Assert.True(textCount > 0);

                // Validate
                using (var doc = PresentationDocument.Open(stream, false))
                {
                    var slideMaster1 = doc.PresentationPart.GetPartById("rId1"); // Get slideMaster1.xml in anther way
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/9/2009");
                    Assert.Equal(textCount, texts.Count());
                }
            }
        }

        /// <summary>
        /// A test for AutoSave set on open
        /// </summary>
        [Fact]
        public void AutoSaveOpenTestWord()
        {
            var s = new OpenSettings
            {
                AutoSave = false,
            };

            using (var stream = GetStream(TestFiles.Complex0docx, true))
            {
                using (var doc = WordprocessingDocument.Open(stream, true, s))
                {
                    // do something, and changes should not be saved.
                    var firstText = doc.MainDocumentPart.Document.Descendants<Text>().First();
                    firstText.Text = "Changed";
                }

                s.AutoSave = true;
                stream.Position = 0;

                using (var doc = WordprocessingDocument.Open(stream, true, s))
                {
                    // check first.
                    var firstText = doc.MainDocumentPart.Document.Descendants<Text>().First();
                    Assert.NotEqual("Changed", firstText.Text);

                    // do changes, and changes shoud be saved.
                    firstText.Text = "Changed";
                }

                stream.Position = 0;

                using (var doc = WordprocessingDocument.Open(stream, true))
                {
                    var firstText = doc.MainDocumentPart.Document.Descendants<Text>().First();
                    Assert.Equal("Changed", firstText.Text);

                    firstText.Text = "Changed2";
                }

                stream.Position = 0;

                using (var docxPackage = System.IO.Packaging.Package.Open(stream, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                using (var doc = WordprocessingDocument.Open(docxPackage, s))
                {
                    var firstText = doc.MainDocumentPart.Document.Descendants<Text>().First();
                    Assert.Equal("Changed2", firstText.Text);

                    firstText.Text = "Changed3";
                }

                stream.Position = 0;

                using (var doc = WordprocessingDocument.Open(stream, false))
                {
                    // check
                    var firstText = doc.MainDocumentPart.Document.Descendants<Text>().First();
                    Assert.Equal("Changed3", firstText.Text);
                }
            }
        }

        [Fact]
        public void AutoSaveOpenTestPowerPoint()
        {
            var s = new OpenSettings
            {
                AutoSave = false,
            };

            using (var stream = GetStream(TestFiles.Autosave, true))
            {
                using (var doc = PresentationDocument.Open(stream, true, s))
                {
                    // do something, and changes should not be saved.
                    var slideMaster1 = doc.PresentationPart.GetPartById("rId1"); // Get slideMaster1.xml
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/7/2009");
                    foreach (var text in texts)
                    {
                        text.Text = "5/9/2009";
                    }
                }

                s.AutoSave = true;
                stream.Position = 0;

                using (var doc = PresentationDocument.Open(stream, true, s))
                {
                    var slideMaster1 = doc.PresentationPart.GetPartById("rId1"); // Get slideMaster1.xml

                    // check first.
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/9/2009");
                    Assert.Empty(texts);

                    // change and save.
                    texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/7/2009");
                    foreach (var text in texts)
                    {
                        text.Text = "5/9/2009";
                    }
                }

                stream.Position = 0;

                using (var doc = PresentationDocument.Open(stream, true))
                {
                    var slideMaster1 = doc.PresentationPart.GetPartById("rId1"); // Get slideMaster1.xml

                    // check first.
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/9/2009");
                    Assert.NotEmpty(texts);

                    // change and save.
                    foreach (var text in texts)
                    {
                        text.Text = "5/10/2009";
                    }
                }

                stream.Position = 0;

                using (var pptxPackage = System.IO.Packaging.Package.Open(stream, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                using (var doc = PresentationDocument.Open(pptxPackage, s))
                {
                    var slideMaster1 = doc.PresentationPart.GetPartById("rId1"); // Get slideMaster1.xml

                    // check first.
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/10/2009");
                    Assert.NotEmpty(texts);

                    // change and save.
                    foreach (var text in texts)
                    {
                        text.Text = "5/11/2009";
                    }
                }

                stream.Position = 0;

                using (var doc = PresentationDocument.Open(stream, false))
                {
                    var slideMaster1 = doc.PresentationPart.GetPartById("rId1"); // Get slideMaster1.xml

                    // check first.
                    var texts = slideMaster1.RootElement.Descendants<a.Text>().Where(t => t.Text == "5/11/2009");
                    Assert.NotEmpty(texts);
                }
            }
        }

        [Fact]
        public void AutoSaveOpenTestExcel()
        {
            var s = new OpenSettings
            {
                AutoSave = false,
            };

            using (var stream = GetStream(TestFiles.Basicspreadsheet, true))
            {
                using (var doc = SpreadsheetDocument.Open(stream, true, s))
                {
                    // do changes, and they should not be saved.
                    var sharedStringsPart = doc.WorkbookPart.GetPartById("rId7");
                    var fonts = sharedStringsPart.RootElement.Descendants<x.RunFont>().Where(e => e.Val == "宋体");
                    foreach (var font in fonts)
                    {
                        font.Val = "微软雅黑";
                    }
                }

                s.AutoSave = true;
                stream.Position = 0;

                using (var doc = SpreadsheetDocument.Open(stream, true, s))
                {
                    // Check first
                    var sharedStringsPart = doc.WorkbookPart.GetPartById("rId7");
                    var fonts = sharedStringsPart.RootElement.Descendants<x.RunFont>().Where(e => e.Val == "微软雅黑");
                    Assert.Empty(fonts);

                    // do changes, and they should be saved.
                    fonts = sharedStringsPart.RootElement.Descendants<x.RunFont>().Where(e => e.Val == "宋体");
                    foreach (var font in fonts)
                    {
                        font.Val = "微软雅黑";
                    }
                }

                stream.Position = 0;

                using (var doc = SpreadsheetDocument.Open(stream, true))
                {
                    var sharedStringsPart = doc.WorkbookPart.GetPartById("rId7");
                    var fonts = sharedStringsPart.RootElement.Descendants<x.RunFont>().Where(e => e.Val == "微软雅黑");
                    Assert.NotEmpty(fonts);
                    foreach (var font in fonts)
                    {
                        font.Val = "仿宋";
                    }
                }

                stream.Position = 0;

                using (var xlsxPackage = System.IO.Packaging.Package.Open(stream, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                using (var doc = SpreadsheetDocument.Open(xlsxPackage, s))
                {
                    var sharedStringsPart = doc.WorkbookPart.GetPartById("rId7");
                    var fonts = sharedStringsPart.RootElement.Descendants<x.RunFont>().Where(e => e.Val == "仿宋");
                    Assert.NotEmpty(fonts);
                    foreach (var font in fonts)
                    {
                        font.Val = "楷体";
                    }
                }

                stream.Position = 0;

                using (var doc = SpreadsheetDocument.Open(stream, false))
                {
                    var sharedStringsPart = doc.WorkbookPart.GetPartById("rId7");
                    var fonts = sharedStringsPart.RootElement.Descendants<x.RunFont>().Where(e => e.Val == "楷体");
                    Assert.NotEmpty(fonts);
                }
            }
        }

        /// <summary>
        /// OpenXmlPackagePartIteraterTest.
        /// </summary>
        [Fact]
        public void OpenXmlPackageGetAllPartsTestWord()
        {
            using (var stream = GetStream(TestFiles.Complex0docx))
            using (var document = WordprocessingDocument.Open(stream, false))
            {
                var parts = document.GetAllParts();

                Assert.Equal(31, parts.Count());

                // Make sure it works well for multi calls
                Assert.Equal(31, parts.Count());
            }
        }

        [Fact]
        public void OpenXmlPackageGetAllPartsTestPowerPoint()
        {
            using (var stream = GetStream(TestFiles.O09_Performance_typical_pptx))
            using (var document = PresentationDocument.Open(stream, false))
            {
                Assert.Equal(65, document.GetAllParts().Count());

                // There is one audio part.
                Assert.Single(document.DataParts);
            }
        }

        /// <summary>
        /// A test for AddRelationshipToPart.
        /// </summary>
        [Fact]
        public void CreateRelationshipToPartTest()
        {
            using (var stream = GetStream(TestFiles.Autosave, true))
            using (var doc = PresentationDocument.Open(stream, true))
            {
                var slide1 = doc.PresentationPart.GetPartById("rId2");
                var slide2 = doc.PresentationPart.GetPartById("rId3");
                var slideLayout1 = slide1.GetPartById("rId1");
                var slideLayout2 = slide2.GetPartById("rId1");

                // add slideLayout2 to slide1
                slide1.DeletePart(slide1.GetPartById("rId1"));

                Assert.Throws<InvalidOperationException>(() => slide1.CreateRelationshipToPart(new SlideLayoutPart()));

                var id = slide1.CreateRelationshipToPart(slideLayout2);
                var part12 = slide1.GetPartById(id);
                Assert.NotNull(part12);
                Assert.Equal(slideLayout2, part12);

                // add slideLayout1 to slide2
                slide2.DeletePart(slideLayout2);

                // try to get exception
                Assert.Throws<InvalidOperationException>(() => slide2.CreateRelationshipToPart(new SlideLayoutPart()));

                var id2 = slide2.CreateRelationshipToPart(slideLayout1, "rId1001");
                Assert.Equal("rId1001", id2);
                var part21 = slide2.GetPartById(id2);
                Assert.NotNull(part21);
                Assert.Equal(slideLayout1, part21);
            }
        }

        [Fact]
        public void WordDocumentTypeIsRetrievedIfAvailable()
        {
            using var stream = GetStream(TestFiles.Templates.Document);
            using var doc = WordprocessingDocument.Open(stream, isEditable: false);

            Assert.Equal(WordprocessingDocumentType.Template, doc.DocumentType);
        }

        [Fact]
        public void SpreadhseetDocumentTypeIsRetrievedIfAvailable()
        {
            using var stream = GetStream(TestFiles.Templates.Spreadsheet);
            using var doc = SpreadsheetDocument.Open(stream, isEditable: false);

            Assert.Equal(SpreadsheetDocumentType.Template, doc.DocumentType);
        }

        [Fact]
        public void PresentationDocumentTypeIsRetrievedIfAvailable()
        {
            using var stream = GetStream(TestFiles.Templates.Presentation);
            using var doc = PresentationDocument.Open(stream, isEditable: false);

            Assert.Equal(PresentationDocumentType.Template, doc.DocumentType);
        }

        [Fact]
        public void DocumentTypeUsesDefault()
        {
            // Arrange
            using var ms = new MemoryStream();

            // Note - if a main part is not created, then no type is persisted
            using (var emptySpreadsheet = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.MacroEnabledTemplate))
            {
            }

            ms.Position = 0;

            // Assert/Act
            using (var result = SpreadsheetDocument.Open(ms, true))
            {
                Assert.Equal(default, result.DocumentType);
            }
        }

        /// <summary>
        /// ChangeDocumentTypeInternalTest.
        /// </summary>
        [Fact]
        public void ChangeDocumentTypeInternalTest()
        {
            using (var stream = GetStream(TestFiles.May_12_04, true))
            using (var doc = WordprocessingDocument.Open(stream, true))
            {
                Assert.Equal(WordprocessingDocumentType.Document, doc.DocumentType);
                var hyperlinksBefore = doc.MainDocumentPart.HyperlinkRelationships.ToArray();
                var externalRelsBefore = doc.MainDocumentPart.ExternalRelationships.ToArray();

                doc.ChangeDocumentType(WordprocessingDocumentType.Template);
                Assert.Equal(WordprocessingDocumentType.Template, doc.DocumentType);

                var hyperlinksAfter = doc.MainDocumentPart.HyperlinkRelationships.ToArray();
                var externalRelsAfter = doc.MainDocumentPart.ExternalRelationships.ToArray();

                // all hyperlink relationships should be keeped.
                Assert.Equal(hyperlinksBefore.Length, hyperlinksAfter.Length);
                for (int i = 0; i < hyperlinksBefore.Length; i++)
                {
                    Assert.Equal(hyperlinksBefore[i].Id, hyperlinksAfter[i].Id);
                    Assert.Equal(hyperlinksBefore[i].IsExternal, hyperlinksAfter[i].IsExternal);
                    Assert.Equal(hyperlinksBefore[i].Uri, hyperlinksAfter[i].Uri);
                }

                // all external relationships should be keeped.
                Assert.Equal(externalRelsBefore.Length, externalRelsAfter.Length);
            }
        }

        /// <summary>
        /// AutoSaveCreateTest.
        /// </summary>
        [Fact]
        public void AutoSaveCreateTestDefault()
        {
            using (var stream = new MemoryStream())
            {
                using (var doc = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document))
                {
                    doc.AddMainDocumentPart();
                    doc.MainDocumentPart.Document = new Document();
                }

                // should be autosaved
                using (var doc = WordprocessingDocument.Open(stream, false))
                {
                    Assert.NotNull(doc.MainDocumentPart.Document);
                }
            }
        }

        [Fact]
        public void AutoSaveCreateTestFalse()
        {
            using (var stream = new MemoryStream())
            {
                using (var doc = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document, false))
                {
                    doc.AddMainDocumentPart();
                    doc.MainDocumentPart.Document = new Document();
                }

                // should not be autosaved
                using (var doc = WordprocessingDocument.Open(stream, false))
                {
                    Assert.Null(doc.MainDocumentPart.Document);
                }
            }
        }

        /// <summary>
        /// LoadPackageWithMediaReferenceTest.
        /// </summary>
        [Fact]
        public void LoadPackageWithMediaReferenceTest()
        {
            using (var stream = GetStream(TestFiles.Mediareference, true))
            {
                using (var testDocument = PresentationDocument.Open(stream, true))
                {
                    Assert.Single(testDocument.DataParts);

                    var slidePart1 = testDocument.PresentationPart.SlideParts.First();
                    Assert.Single(slidePart1.DataPartReferenceRelationships);
                    Assert.IsType<MediaReferenceRelationship>(slidePart1.DataPartReferenceRelationships.First());
                    var mediaReference = slidePart1.DataPartReferenceRelationships.First() as MediaReferenceRelationship;
                    Assert.Same(slidePart1, mediaReference.Container);

                    var slidePart2 = testDocument.PresentationPart.SlideParts.ElementAt(1);
                    Assert.Equal(2, slidePart2.DataPartReferenceRelationships.Count());
                    Assert.Same(slidePart2, slidePart2.DataPartReferenceRelationships.First().Container);
                    Assert.Same(slidePart2, slidePart2.DataPartReferenceRelationships.Last().Container);

                    var dataPart = testDocument.DataParts.First();
                    Assert.IsType<MediaDataPart>(dataPart);
                    Assert.Same(testDocument, dataPart.OpenXmlPackage);
                    Assert.NotNull(dataPart.PackagePart);
                    Assert.Same(testDocument.Package.GetPart(dataPart.Uri), dataPart.PackagePart);
                    Assert.Equal("audio/wav", dataPart.ContentType);
                    Assert.Equal(3, dataPart.GetDataPartReferenceRelationships().Count());

                    // Add a new reference
                    var newReference = slidePart1.AddAudioReferenceRelationship(mediaReference.DataPart as MediaDataPart);
                    Assert.Equal(2, slidePart1.DataPartReferenceRelationships.Count());
                    Assert.Same(slidePart1, newReference.Container);
                    Assert.Same(mediaReference.DataPart, newReference.DataPart);

                    // delete the old reference
                    slidePart1.DeleteReferenceRelationship(mediaReference);
                    Assert.Single(slidePart1.DataPartReferenceRelationships);
                    Assert.Null(mediaReference.Container);

                    // delete one reference from slide2
                    DataPartReferenceRelationship dataPartReference = slidePart2.DataPartReferenceRelationships.First();
                    slidePart2.DeleteReferenceRelationship(dataPartReference.Id);
                    Assert.Single(slidePart2.DataPartReferenceRelationships);
                    Assert.Null(mediaReference.Container);
                }

                stream.Flush();
                stream.Seek(0, SeekOrigin.Begin);

                using (var testDocument = PresentationDocument.Open(stream, true))
                {
                    Assert.Single(testDocument.DataParts);

                    var slidePart1 = testDocument.PresentationPart.SlideParts.First();
                    Assert.Single(slidePart1.DataPartReferenceRelationships);
                    Assert.IsType<AudioReferenceRelationship>(slidePart1.DataPartReferenceRelationships.First());
                    var audioReference = slidePart1.DataPartReferenceRelationships.First() as AudioReferenceRelationship;
                    Assert.Same(slidePart1, audioReference.Container);

                    var slidePart2 = testDocument.PresentationPart.SlideParts.ElementAt(1);
                    Assert.Single(slidePart2.DataPartReferenceRelationships);
                    Assert.Same(slidePart2, slidePart2.DataPartReferenceRelationships.First().Container);

                    var dataPart = testDocument.DataParts.First();
                    Assert.IsType<MediaDataPart>(dataPart);
                    Assert.Same(testDocument, dataPart.OpenXmlPackage);
                    Assert.NotNull(dataPart.PackagePart);
                    Assert.Same(testDocument.Package.GetPart(dataPart.Uri), dataPart.PackagePart);
                    Assert.Equal("audio/wav", dataPart.ContentType);
                    Assert.Equal(2, dataPart.GetDataPartReferenceRelationships().Count());

                    // remove all the reference
                    slidePart1.DeleteReferenceRelationship(audioReference);
                    slidePart2.DeleteReferenceRelationship(slidePart2.DataPartReferenceRelationships.First().Id);

                    // dataPart is still there
                    dataPart = testDocument.DataParts.First();
                    Assert.IsType<MediaDataPart>(dataPart);
                    Assert.Same(testDocument, dataPart.OpenXmlPackage);
                    Assert.NotNull(dataPart.PackagePart);
                    Assert.Empty(dataPart.GetDataPartReferenceRelationships());
                }

                stream.Flush();
                stream.Seek(0, SeekOrigin.Begin);

                using (var testDocument = PresentationDocument.Open(stream, false))
                {
                    // there should be no data part any more
                    Assert.Empty(testDocument.DataParts);
                }
            }
        }

        /// <summary>
        /// MediaDataPartReferenceTest.
        /// </summary>
        [Fact]
        public void MediaDataPartReferenceTest()
        {
            using (var stream = new MemoryStream())
            {
                using (var doc = PresentationDocument.Create(stream, PresentationDocumentType.Presentation))
                {
                    doc.AddPresentationPart();
                    var mediaDataPart = doc.CreateMediaDataPart("audio/wav", ".wav");

                    Assert.EndsWith(".wav", mediaDataPart.Uri.OriginalString);

                    var aviDataPart = doc.CreateMediaDataPart(MediaDataPartType.Avi);

                    Assert.EndsWith(".avi", aviDataPart.Uri.OriginalString);
                }
            }
        }

        // TODO: Remove test copy
        private void PrepareTestFile(string testFile, byte[] source)
        {
            if (File.Exists(testFile))
            {
                File.Delete(testFile);
            }

            using (var writer = new BinaryWriter(new FileStream(testFile, FileMode.Create, FileAccess.ReadWrite)))
            {
                writer.Write(source, 0, source.Length);
            }
        }

        /// <summary>
        /// A test for opening Strict Word files as read-write(editable)/read-only
        /// </summary>
        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void StrictFileOpenTestWord(bool isEditable)
        {
            using (var stream = GetStream(TestFiles.AnnotationRef, isEditable))
            using (var doc = WordprocessingDocument.Open(stream, isEditable))
            {
                // Should open without exception.

                // Referencing doc.MainDocumentPart.RootElement triggers to load the MainDocumentPart which underneath
                // calls methods in XmlConvertingReader with the strictRelationshipFound flag enabled.
                Assert.NotNull(doc.MainDocumentPart.RootElement);
            }
        }

        /// <summary>
        /// A test for opening Strict PowerPoint files as read-write(editable)/read-only
        /// </summary>
        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void StrictFileOpenTestPowerpoint(bool isEditable)
        {
            using (var stream = GetStream(TestFiles.Algn_tab_TabAlignment, isEditable))
            using (var doc = PresentationDocument.Open(stream, isEditable))
            {
                // Should open without exception.

                // Calling doc.PresentationPart.RootElement triggers to load the PresentationPart which underneath
                // calls methods in XmlConvertingReader with the strictRelationshipFound flag enabled.
                Assert.NotNull(doc.PresentationPart.RootElement);
            }
        }

        /// <summary>
        /// A test for opening Strict PowerPoint files as read-write(editable)/read-only
        /// </summary>
        [Theory]
        [InlineData(true)]
        [InlineData(false)]
        public void StrictFileOpenTestExcelReadOnly(bool isEditable)
        {
            using (var stream = GetStream(TestFiles.Comments, isEditable))
            using (var doc = SpreadsheetDocument.Open(stream, isEditable))
            {
                // Should open without exception.

                // Referencing doc.WorkbookPart.RootElement triggers to load the WorkbookPart which underneath
                // calls methods in XmlConvertingReader with the strictRelationshipFound flag enabled.
                Assert.NotNull(doc.WorkbookPart.RootElement);
            }
        }

        /// <summary>
        /// A test for opening O15 files
        /// Check if WebExtension in the test file is accessible.
        /// If WebExtension is not integrated in the SDK, we can't even compile this unit test project...
        /// </summary>
        [Fact]
        public void O15FileOpenTest()
        {
            var settings2012 = new OpenSettings()
            {
                MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings(MarkupCompatibilityProcessMode.ProcessAllParts, FileFormatVersions.Office2013),
            };

            using (var stream = GetStream(TestFiles.Youtube))
            using (var doc = SpreadsheetDocument.Open(stream, false, settings2012))
            {
                var worksheetPart = doc.WorkbookPart.WorksheetParts.First();
                var webExtensionPart = worksheetPart.DrawingsPart.WebExtensionParts.First();

                Assert.NotNull(webExtensionPart);
            }
        }
    }
}
